Promise 执行跟踪
¥Promise execution tracking
默认情况下,由于 V8 提供的 promise 自省 API 相对昂贵,因此不会为 promise 执行分配 asyncId。这意味着默认情况下,使用 promise 或 async/await 的程序将无法正确执行并触发 promise 回调上下文的 id。
¥By default, promise executions are not assigned asyncIds due to the relatively
expensive nature of the promise introspection API provided by
V8. This means that programs using promises or async/await will not get
correct execution and trigger ids for promise callback contexts by default.
import { executionAsyncId, triggerAsyncId } from 'node:async_hooks';
Promise.resolve(1729).then(() => {
console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`);
});
// produces:
// eid 1 tid 0const { executionAsyncId, triggerAsyncId } = require('node:async_hooks');
Promise.resolve(1729).then(() => {
console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`);
});
// produces:
// eid 1 tid 0注意 then() 回调声称已在外部范围的上下文中执行,即使涉及异步的跃点。另外,triggerAsyncId 的值是 0,这意味着我们缺少有关导致(触发)then() 回调被执行的资源的上下文。
¥Observe that the then() callback claims to have executed in the context of the
outer scope even though there was an asynchronous hop involved. Also,
the triggerAsyncId value is 0, which means that we are missing context about
the resource that caused (triggered) the then() callback to be executed.
通过 async_hooks.createHook 安装异步钩子启用 promise 执行跟踪:
¥Installing async hooks via async_hooks.createHook enables promise execution
tracking:
import { createHook, executionAsyncId, triggerAsyncId } from 'node:async_hooks';
createHook({ init() {} }).enable(); // forces PromiseHooks to be enabled.
Promise.resolve(1729).then(() => {
console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`);
});
// produces:
// eid 7 tid 6const { createHook, executionAsyncId, triggerAsyncId } = require('node:async_hooks');
createHook({ init() {} }).enable(); // forces PromiseHooks to be enabled.
Promise.resolve(1729).then(() => {
console.log(`eid ${executionAsyncId()} tid ${triggerAsyncId()}`);
});
// produces:
// eid 7 tid 6在这个示例中,添加任何实际的钩子函数启用了对 promise 的跟踪。上面的例子中有两个 promise;Promise.resolve() 创建的 promise 和调用 then() 返回的 promise。在上面的示例中,第一个 promise 得到 asyncId 6,后者得到 asyncId 7。在执行 then() 回调期间,我们在 asyncId 7 的 promise 上下文中执行。此 promise 由异步资源 6 触发。
¥In this example, adding any actual hook function enabled the tracking of
promises. There are two promises in the example above; the promise created by
Promise.resolve() and the promise returned by the call to then(). In the
example above, the first promise got the asyncId 6 and the latter got
asyncId 7. During the execution of the then() callback, we are executing
in the context of promise with asyncId 7. This promise was triggered by
async resource 6.
promise 的另一个微妙之处是 before 和 after 回调仅在链式 promise 上运行。这意味着不是由 then()/catch() 创建的 promise 不会触发 before 和 after 回调。有关更多详细信息,请参阅 V8 PromiseHooks API 的详细信息。
¥Another subtlety with promises is that before and after callbacks are run
only on chained promises. That means promises not created by then()/catch()
will not have the before and after callbacks fired on them. For more details
see the details of the V8 PromiseHooks API.