Spec-Zone.ru › Node.js 10 LTS

Async Hooks

Устойчивость: 1 - Экспериментальная

Модуль async_hooks предоставляет API для регистрации обратных вызовов, отслеживающих жизненный цикл асинхронных ресурсов, созданных внутри приложения Node.js. Он доступен с помощью:

const async_hooks = require('async_hooks');

Терминология

Асинхронный ресурс представляет собой объект с ассоциированным обратным вызовом. Этот обратный вызов может вызываться несколько раз, например, событие 'connection' в net.createServer(), или только один раз, как в fs.open(). Ресурс также может быть закрыт до вызова обратного вызова. AsyncHook не явно различает эти различные случаи, но представляет их как абстрактное понятие — ресурс.

Если используются Worker, каждый поток имеет независимый async_hooks интерфейс, и каждый поток будет использовать новый набор асинхронных идентификаторов.

Публичный API

Обзор

Ниже приведён простой обзор публичного API.

const async_hooks = require('async_hooks');

// Return the ID of the current execution context.
const eid = async_hooks.executionAsyncId();

// Return the ID of the handle responsible for triggering the callback of the
// current execution scope to call.
const tid = async_hooks.triggerAsyncId();

// Create a new AsyncHook instance. All of these callbacks are optional.
const asyncHook =
    async_hooks.createHook({ init, before, after, destroy, promiseResolve });

// Allow callbacks of this AsyncHook instance to call. This is not an implicit
// action after running the constructor, and must be explicitly run to begin
// executing callbacks.
asyncHook.enable();

// Disable listening for new asynchronous events.
asyncHook.disable();

//
// The following are the callbacks that can be passed to createHook().
//

// init is called during object construction. The resource may not have
// completed construction when this callback runs, therefore all fields of the
// resource referenced by "asyncId" may not have been populated.
function init(asyncId, type, triggerAsyncId, resource) { }

// before is called just before the resource's callback is called. It can be
// called 0-N times for handles (e.g. TCPWrap), and will be called exactly 1
// time for requests (e.g. FSReqWrap).
function before(asyncId) { }

// after is called just after the resource's callback has finished.
function after(asyncId) { }

// destroy is called when an AsyncWrap instance is destroyed.
function destroy(asyncId) { }

// promiseResolve is called only for promise resources, when the
// `resolve` function passed to the `Promise` constructor is invoked
// (either directly or through other means of resolving a promise).
function promiseResolve(asyncId) { }

async_hooks.createHook(callbacks)[src]

Добавлен в: v8.1.0
  • callbacks <Объект> Регистрируемые Обратные вызовы обработчика

    • init <Функция> Обратный вызов init.
    • before <Функция> Обратный вызов before.
    • after <Функция> Обратный вызов after.
    • destroy <Функция> Обратный вызов destroy.
  • Возвращает: <AsyncHook> Экземпляр, используемый для отключения и включения обработчиков

Регистрирует функции, которые вызываются для различных событий жизненного цикла каждой асинхронной операции.

Обратные вызовы init()/before()/after()/destroy() вызываются для соответствующего асинхронного события в течение жизненного цикла ресурса.

Все обратные вызовы необязательны. Например, если нужно отслеживать только очистку ресурса, то нужно передать только обратный вызов destroy. Подробности всех функций, которые можно передать в callbacks, приведены в разделе Обратные вызовы обработчика.

const async_hooks = require('async_hooks');

const asyncHook = async_hooks.createHook({
  init(asyncId, type, triggerAsyncId, resource) { },
  destroy(asyncId) { }
});

Обратите внимание, что обратные вызовы будут унаследованы через цепочку прототипов:

class MyAsyncCallbacks {
  init(asyncId, type, triggerAsyncId, resource) { }
  destroy(asyncId) {}
}

class MyAddedCallbacks extends MyAsyncCallbacks {
  before(asyncId) { }
  after(asyncId) { }
}

const asyncHook = async_hooks.createHook(new MyAddedCallbacks());
Обработка ошибок

Если любой из обратных вызовов AsyncHook выбрасывает ошибку, приложение выведет трассировку стека и завершится. Путь завершения аналогичен пути завершения при неуловленной ошибке, но все слушатели 'uncaughtException' удаляются, что принуждает процесс к завершению. Обратные вызовы 'exit' всё равно будут вызваны, если приложение не запущено с --abort-on-uncaught-exception, в этом случае будет выведена трассировка стека, и приложение завершится, оставив файл core.

Причина такого поведения обработки ошибок заключается в том, что эти обратные вызовы выполняются в потенциально нестабильных точках жизненного цикла объекта, например, во время создания и уничтожения класса. По этой причине считается необходимым быстро завершить процесс, чтобы предотвратить непреднамеренный отказ в будущем. Это может быть изменено в будущем, если будет проведен всесторонний анализ, чтобы гарантировать, что исключение может следовать нормальному потоку управления без непреднамеренных побочных эффектов.

Вывод в обратных вызовах AsyncHooks

Поскольку вывод в консоль является асинхронной операцией, console.log() вызовет обратные вызовы AsyncHooks. Использование console.log() или аналогичных асинхронных операций внутри функции обратного вызова AsyncHooks приведет к бесконечной рекурсии. Простым решением при отладке является использование синхронной операции записи в лог, например, fs.writeFileSync(file, msg, flag). Это запишет в файл и не вызовет рекурсию AsyncHooks, поскольку она является синхронной.

const fs = require('fs');
const util = require('util');

function debug(...args) {
  // use a function like this one when debugging inside an AsyncHooks callback
  fs.writeFileSync('log.out', `${util.format(...args)}\n`, { flag: 'a' });
}

Если для ведения журнала требуется асинхронная операция, можно отследить причину асинхронной операции, используя информацию, предоставляемую самим AsyncHooks. Затем запись в журнал должна быть пропущена, если она сама вызвала обратный вызов AsyncHooks. Таким образом, бесконечная рекурсия прерывается.

asyncHook.enable()

  • Возвращает: <AsyncHook> Ссылка на asyncHook.

Включает обратные вызовы для данного экземпляра AsyncHook. Если обратные вызовы не предоставлены, включение является пустой операцией.

Экземпляр AsyncHook отключён по умолчанию. Если экземпляр AsyncHook должен быть включён сразу после создания, можно использовать следующую конструкцию.

const async_hooks = require('async_hooks');

const hook = async_hooks.createHook(callbacks).enable();

asyncHook.disable()

  • Возвращает: <AsyncHook> Ссылка на asyncHook.

Отключает обратные вызовы для данного экземпляра AsyncHook из глобального пула AsyncHook обратных вызовов, которые должны быть выполнены. После отключения обработчик больше не будет вызываться до его включения.

Для обеспечения согласованности API disable() также возвращает экземпляр AsyncHook.

Обратные вызовы обработчика

Ключевые события в жизненном цикле асинхронных событий были разделены на четыре области: создание, до/после вызова обратного вызова и при уничтожении экземпляра.

init(asyncId, type, triggerAsyncId, resource)
  • asyncId <число> Уникальный идентификатор асинхронного ресурса.
  • type <строка> Тип асинхронного ресурса.
  • triggerAsyncId <число> Уникальный идентификатор асинхронного ресурса, в контексте выполнения которого был создан данный асинхронный ресурс.
  • resource <объект> Ссылка на ресурс, представляющий асинхронную операцию, который необходимо освободить во время destroy.

Вызывается при создании класса, который имеет возможность генерировать асинхронное событие. Это не означает, что экземпляр должен вызвать before/after до вызова destroy, только то, что такая возможность существует.

Это поведение можно наблюдать, открыв ресурс, а затем закрыв его, прежде чем ресурс может быть использован. Следующий фрагмент кода демонстрирует это.

require('net').createServer().listen(function() { this.close(); });
// OR
clearTimeout(setTimeout(() => {}, 10));

Каждый новый ресурс получает присвоенный ID, уникальный в рамках текущего экземпляра Node.js.

type

type — это строка, определяющая тип ресурса, который вызвал init. Как правило, он соответствует имени конструктора ресурса.

FSEVENTWRAP, FSREQWRAP, GETADDRINFOREQWRAP, GETNAMEINFOREQWRAP, HTTPPARSER,
JSSTREAM, PIPECONNECTWRAP, PIPEWRAP, PROCESSWRAP, QUERYWRAP, SHUTDOWNWRAP,
SIGNALWRAP, STATWATCHER, TCPCONNECTWRAP, TCPSERVERWRAP, TCPWRAP, TIMERWRAP,
TTYWRAP, UDPSENDWRAP, UDPWRAP, WRITEWRAP, ZLIB, SSLCONNECTION, PBKDF2REQUEST,
RANDOMBYTESREQUEST, TLSWRAP, Timeout, Immediate, TickObject

Также существует тип ресурса PROMISE, который используется для отслеживания экземпляров Promise и асинхронной работы, запланированной ими.

Пользователи могут определять свои собственные type при использовании публичного API для встраивания.

Возможны коллизии имён типов. Встраивающим компонентам рекомендуется использовать уникальные префиксы, например, имя пакета npm, чтобы предотвратить коллизии при прослушивании обработчиков.

triggerAsyncId

triggerAsyncId — это asyncId ресурса, который вызвал (или «спровоцировал») инициализацию нового ресурса и вызов init. Это отличается от async_hooks.executionAsyncId(), который только показывает когда был создан ресурс, в то время как triggerAsyncId показывает почему был создан ресурс.

Следующее — простой пример triggerAsyncId:

async_hooks.createHook({
  init(asyncId, type, triggerAsyncId) {
    const eid = async_hooks.executionAsyncId();
    fs.writeSync(
      1, `${type}(${asyncId}): trigger: ${triggerAsyncId} execution: ${eid}\n`);
  }
}).enable();

require('net').createServer((conn) => {}).listen(8080);

Вывод при обращении к серверу с nc localhost 8080:

TCPSERVERWRAP(5): trigger: 1 execution: 1
TCPWRAP(7): trigger: 5 execution: 0

TCPSERVERWRAP — это сервер, принимающий подключения.

TCPWRAP — это новое подключение от клиента. При установлении нового подключения экземпляр TCPWrap сразу же создаётся. Это происходит вне стека JavaScript. (executionAsyncId() 0 означает, что он выполняется из C++ без стека JavaScript над ним.) С этой информацией было бы невозможно связать ресурсы в терминах того, что их заставило создать, поэтому triggerAsyncId получает задачу распространять информацию о том, какой ресурс отвечает за существование нового ресурса.

resource

resource — это объект, представляющий фактический асинхронный ресурс, который был инициализирован. Он может содержать полезную информацию, которая может варьироваться в зависимости от значения type. Например, для типа ресурса GETADDRINFOREQWRAP resource предоставляет имя хоста, используемое при поиске IP-адреса хоста в net.Server.listen(). API для доступа к этой информации сейчас не считается публичным, но с помощью API для встраивания пользователи могут предоставлять и документировать свои собственные объекты ресурсов. Например, такой объект ресурса может содержать выполняемый SQL-запрос.

В случае с обещаниями, объект resource будет иметь свойство promise, которое ссылается на обещание Promise, которое инициализируется, и свойство isChainedPromise, установленное в значение true, если у обещания есть родительское обещание, и в значение false в противном случае. Например, в случае b = a.then(handler), a считается родительским Promise обещанием для b. В данном случае, b считается цепочным обещанием.

В некоторых случаях объект ресурса повторно используется по соображениям производительности, поэтому небезопасно использовать его в качестве ключа в WeakMap или добавлять к нему свойства.

Пример контекста асинхронной операции

Ниже приведен пример с дополнительной информацией о вызовах init между вызовами before и after, а также о том, как будет выглядеть обратный вызов listen(). Форматирование вывода немного более подробное, чтобы легче было увидеть контекст вызова.

let indent = 0;
async_hooks.createHook({
  init(asyncId, type, triggerAsyncId) {
    const eid = async_hooks.executionAsyncId();
    const indentStr = ' '.repeat(indent);
    fs.writeSync(
      1,
      `${indentStr}${type}(${asyncId}):` +
      ` trigger: ${triggerAsyncId} execution: ${eid}\n`);
  },
  before(asyncId) {
    const indentStr = ' '.repeat(indent);
    fs.writeFileSync('log.out',
                     `${indentStr}before:  ${asyncId}\n`, { flag: 'a' });
    indent += 2;
  },
  after(asyncId) {
    indent -= 2;
    const indentStr = ' '.repeat(indent);
    fs.writeFileSync('log.out',
                     `${indentStr}after:  ${asyncId}\n`, { flag: 'a' });
  },
  destroy(asyncId) {
    const indentStr = ' '.repeat(indent);
    fs.writeFileSync('log.out',
                     `${indentStr}destroy:  ${asyncId}\n`, { flag: 'a' });
  },
}).enable();

require('net').createServer(() => {}).listen(8080, () => {
  // Let's wait 10ms before logging the server started.
  setTimeout(() => {
    console.log('>>>', async_hooks.executionAsyncId());
  }, 10);
});

Вывод после только запуска сервера:

TCPSERVERWRAP(5): trigger: 1 execution: 1
TickObject(6): trigger: 5 execution: 1
before:  6
  Timeout(7): trigger: 6 execution: 6
after:   6
destroy: 6
before:  7
>>> 7
  TickObject(8): trigger: 7 execution: 7
after:   7
before:  8
after:   8

Как показано в примере, executionAsyncId() и execution каждый указывают значение текущего контекста выполнения; что определяется вызовами before и after.

Только использование execution для построения графика распределения ресурсов приводит к следующему:

Timeout(7) -> TickObject(6) -> root(1)

TCPSERVERWRAP не входит в этот график, хотя он был причиной вызова console.log(). Это связано с тем, что привязка к порту без имени хоста является синхронной операцией, но для поддержания полностью асинхронного API обратный вызов пользователя помещается в process.nextTick().

График показывает только когда был создан ресурс, а не почему, поэтому для отслеживания почему используйте triggerAsyncId.

before(asyncId)
  • asyncId <число>

Когда инициируется асинхронная операция (например, сервер TCP получает новое соединение) или она завершается (например, запись данных на диск), вызывается обратный вызов для уведомления пользователя. Обратный вызов before вызывается непосредственно перед выполнением указанного обратного вызова. asyncId — это уникальный идентификатор, назначенный ресурсу, который собирается выполнить обратный вызов.

Обратный вызов before будет вызываться 0 до N раз. Обратный вызов before обычно вызывается 0 раз, если асинхронная операция была отменена или, например, если сервер TCP не получает никаких соединений. Постоянные асинхронные ресурсы, такие как сервер TCP, обычно вызывают обратный вызов before несколько раз, в то время как другие операции, такие как fs.open(), вызывают его только один раз.

after(asyncId)
  • asyncId <число>

Вызывается сразу после завершения обратного вызова, указанного в before.

Если во время выполнения обратного вызова произойдет непредвиденное исключение, то after будет выполнен после того, как событие 'uncaughtException' будет излучено или обработчик domain выполнит свою работу.

destroy(asyncId)
  • asyncId <число>

Вызывается после уничтожения ресурса, соответствующего asyncId. Он также вызывается асинхронно из API emitDestroy() встраиваемой среды.

Некоторые ресурсы зависят от сборки мусора для очистки, поэтому если ссылка на объект resource , переданный в init, сохраняется, то destroy может никогда не быть вызванным, что приведёт к утечке памяти в приложении. Если ресурс не зависит от сборки мусора, это не будет проблемой.

promiseResolve(asyncId)
  • asyncId <число>

Вызывается, когда функция resolve, переданная конструктору Promise, вызывается (либо напрямую, либо через другие средства разрешения обещания).

Обратите внимание, что resolve() не выполняет никаких наблюдаемых синхронных операций.

Обещание Promise необязательно выполнено или отклонено на этом этапе, если Promise было разрешено путём принятия состояния другого Promise.

new Promise((resolve) => resolve(true)).then((a) => {});

вызывает следующие обратные вызовы:

init for PROMISE with id 5, trigger id: 1
  promise resolve 5      # corresponds to resolve(true)
init for PROMISE with id 6, trigger id: 5  # the Promise returned by then()
  before 6               # the then() callback is entered
  promise resolve 6      # the then() callback resolves the promise by returning
  after 6

async_hooks.executionAsyncId()

История
Версия Изменения
v8.2.0

Переименовано из currentId

v8.1.0

Добавлен в: v8.1.0

  • Возвращает: <число> asyncId текущего контекста выполнения. Полезно отслеживать, когда что-то вызывается.
const async_hooks = require('async_hooks');

console.log(async_hooks.executionAsyncId());  // 1 - bootstrap
fs.open(path, 'r', (err, fd) => {
  console.log(async_hooks.executionAsyncId());  // 6 - open()
});

Идентификатор, возвращаемый executionAsyncId(), связан с временем выполнения, а не с причинно-следственной связью (что охватывается triggerAsyncId()):

const server = net.createServer((conn) => {
  // Returns the ID of the server, not of the new connection, because the
  // callback runs in the execution scope of the server's MakeCallback().
  async_hooks.executionAsyncId();

}).listen(port, () => {
  // Returns the ID of a TickObject (i.e. process.nextTick()) because all
  // callbacks passed to .listen() are wrapped in a nextTick().
  async_hooks.executionAsyncId();
});

Обратите внимание, что контексты обещаний могут не получать точные executionAsyncIds по умолчанию. Смотрите раздел о отслеживании выполнения обещаний.

async_hooks.triggerAsyncId()

  • Возвращает: <число> Идентификатор ресурса, ответственного за вызов обратного вызова, который выполняется в данный момент.
const server = net.createServer((conn) => {
  // The resource that caused (or triggered) this callback to be called
  // was that of the new connection. Thus the return value of triggerAsyncId()
  // is the asyncId of "conn".
  async_hooks.triggerAsyncId();

}).listen(port, () => {
  // Even though all callbacks passed to .listen() are wrapped in a nextTick()
  // the callback itself exists because the call to the server's .listen()
  // was made. So the return value would be the ID of the server.
  async_hooks.triggerAsyncId();
});

Обратите внимание, что контексты обещаний могут не получать действительные triggerAsyncId по умолчанию. Смотрите раздел о отслеживании выполнения обещаний.

Отслеживание выполнения обещаний

По умолчанию выполнение обещаний не присваиваются asyncId из-за относительно высокой стоимости предоставленного V8 API интроспекции обещаний. Это означает, что программы, использующие обещания или async/await, по умолчанию не получат правильных идентификаторов выполнения и срабатывания для контекстов обратных вызовов обещаний.

const ah = require('async_hooks');
Promise.resolve(1729).then(() => {
  console.log(`eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`);
});
// produces:
// eid 1 tid 0

Обратите внимание, что обратный вызов then() утверждает, что был выполнен в контексте внешней области, даже если был асинхронный переход. Также обратите внимание, что значение triggerAsyncId равно 0, что означает, что нам не хватает контекста о ресурсе, который вызвал (сработал) обратный вызов then() для выполнения.

Установка асинхронных хуков через async_hooks.createHook включает отслеживание выполнения обещаний:

const ah = require('async_hooks');
ah.createHook({ init() {} }).enable(); // forces PromiseHooks to be enabled.
Promise.resolve(1729).then(() => {
  console.log(`eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`);
});
// produces:
// eid 7 tid 6

В этом примере добавление любой реальной функции хука позволило отслеживать выполнение обещаний. В примере выше есть два обещания: обещание, созданное Promise.resolve(), и обещание, возвращаемое вызовом then(). В примере выше первое обещание получило asyncId 6, а последнее — asyncId 7. Во время выполнения обратного вызова then(), мы выполняем в контексте обещания с asyncId 7. Это обещание было вызвано асинхронным ресурсом 6.

Ещё одна тонкость с обещаниями заключается в том, что обратные вызовы before и after выполняются только для цепочных обещаний. Это означает, что обещания, не созданные then()/catch(), не будут иметь обратные вызовы before и after.

Для получения дополнительной информации см. раздел API V8 PromiseHooks.

API JavaScript для встраиваемой среды

Разработчики библиотек, которые обрабатывают собственные асинхронные ресурсы, выполняя задачи, такие как ввод-вывод, пулы соединений или управление очередями обратных вызовов, могут использовать API AsyncWrap JavaScript, чтобы гарантировать, что будут вызваны все необходимые обратные вызовы.

Класс: AsyncResource[src]

Класс AsyncResource предназначен для расширения асинхронными ресурсами встраиваемой среды. С его помощью пользователи могут легко вызывать события жизненного цикла своих ресурсов.

Хук init срабатывает при создании AsyncResource.

Ниже представлен обзор API AsyncResource.

const { AsyncResource, executionAsyncId } = require('async_hooks');

// AsyncResource() is meant to be extended. Instantiating a
// new AsyncResource() also triggers init. If triggerAsyncId is omitted then
// async_hook.executionAsyncId() is used.
const asyncResource = new AsyncResource(
  type, { triggerAsyncId: executionAsyncId(), requireManualDestroy: false }
);

// Run a function in the execution context of the resource. This will
// * establish the context of the resource
// * trigger the AsyncHooks before callbacks
// * call the provided function `fn` with the supplied arguments
// * trigger the AsyncHooks after callbacks
// * restore the original execution context
asyncResource.runInAsyncScope(fn, thisArg, ...args);

// Call AsyncHooks destroy callbacks.
asyncResource.emitDestroy();

// Return the unique ID assigned to the AsyncResource instance.
asyncResource.asyncId();

// Return the trigger ID for the AsyncResource instance.
asyncResource.triggerAsyncId();

new AsyncResource(type[, options])[src]

  • type <строка> Тип асинхронного события.
  • options <Объект>

    • triggerAsyncId <число> Идентификатор контекста выполнения, создавшего это асинхронное событие. По умолчанию: executionAsyncId().
    • requireManualDestroy <логическое значение> Отключает автоматическую emitDestroy при удалении объекта из памяти. Обычно это не нужно устанавливать (даже если emitDestroy вызывается вручную), если только не извлекается asyncId ресурса и вызывается emitDestroy чувствительного API с ним. По умолчанию: false.

Пример использования:

class DBQuery extends AsyncResource {
  constructor(db) {
    super('DBQuery');
    this.db = db;
  }

  getInfo(query, callback) {
    this.db.get(query, (err, data) => {
      this.runInAsyncScope(callback, null, err, data);
    });
  }

  close() {
    this.db = null;
    this.emitDestroy();
  }
}

asyncResource.runInAsyncScope(fn[, thisArg, ...args])[src]

Добавлен в: v9.6.0
  • fn <Функция> Функция, которая должна быть вызвана в контексте выполнения этого асинхронного ресурса.
  • thisArg <любой> Объект, который должен использоваться в качестве получателя для вызова функции.
  • ...args <любой> Необязательные аргументы, которые нужно передать функции.

Вызывает предоставленную функцию с предоставленными аргументами в контексте выполнения асинхронного ресурса. Это позволит установить контекст, запустить AsyncHooks до обратных вызовов, вызвать функцию, запустить AsyncHooks после обратных вызовов и восстановить исходный контекст выполнения.

asyncResource.emitBefore()[src]

Устарело с версии: v9.6.0
Уровень стабильности: 0 - Устарело: Используйте asyncResource.runInAsyncScope() вместо этого.

Вызывает все before обратные вызовы, чтобы уведомить о входе в новый асинхронный контекст выполнения. Если выполняются вложенные вызовы emitBefore(), стек asyncId будет отслеживаться и правильно разворачиваться.

before и after вызовы должны разворачиваться в том же порядке, в котором они были вызваны. В противном случае произойдёт необратимая ошибка, и процесс будет прерван. По этой причине API emitBefore и emitAfter считаются устаревшими. Пожалуйста, используйте runInAsyncScope, так как это обеспечивает гораздо более безопасную альтернативу.

asyncResource.emitAfter()[src]

Устарело с версии: v9.6.0
Уровень стабильности: 0 - Устарело: Используйте asyncResource.runInAsyncScope() вместо этого.

Вызывает все after обратные вызовы. Если были выполнены вложенные вызовы emitBefore(), убедитесь, что стек разворачивается корректно. В противном случае будет выброшено исключение.

Если обратный вызов пользователя вызывает исключение, emitAfter() автоматически будет вызван для всех asyncId в стеке, если ошибка обрабатывается областью или 'uncaughtException' обработчиком.

before и after вызовы должны разворачиваться в том же порядке, что и вызов. В противном случае произойдёт необратимая ошибка, и процесс завершится. По этой причине API emitBefore и emitAfter считаются устаревшими. Пожалуйста, используйте runInAsyncScope, так как это обеспечивает более безопасную альтернативу.

asyncResource.emitDestroy()[src]

  • Возвращает: <AsyncResource> Ссылка на asyncResource.

Вызывает все destroy хуки. Это должно вызываться только один раз. Если оно вызывается более одного раза, будет выброшено исключение. Это обязательно вызывать вручную. Если ресурс будет собран сборщиком мусора, то destroy хуки никогда не будут вызваны.

asyncResource.asyncId()[src]

  • Возвращает: <число> Уникальное asyncId значение, назначенное ресурсу.

asyncResource.triggerAsyncId()[src]

  • Возвращает: <число> То же самое triggerAsyncId, что передаётся в конструктор AsyncResource.

© Joyent, Inc. and other Node contributors
Licensed under the MIT License.
Node.js is a trademark of Joyent, Inc. and is used with its permission.
We are not endorsed by or affiliated with Joyent.
https://nodejs.org/dist/latest-v10.x/docs/api/async_hooks.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API