Promise 执行跟踪
默认情况下,由于 V8 提供的 promise 自省 API 相对昂贵,因此不会为 promise 执行分配 asyncId
。
这意味着默认情况下,使用 promise 或 async
/await
的程序将无法正确执行并触发 promise 回调上下文的 id。
const ah = require('async_hooks');
Promise.resolve(1729).then(() => {
console.log(`eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`);
});
// 产生:
// eid 1 tid 0
注意 then()
回调声称已在外部范围的上下文中执行,即使涉及异步的跃点。
另外,triggerAsyncId
的值是 0
,这意味着我们缺少有关导致(触发)then()
回调被执行的资源的上下文。
通过 async_hooks.createHook
安装异步钩子启用 promise 执行跟踪:
const ah = require('async_hooks');
ah.createHook({ init() {} }).enable(); // 强制启用 PromiseHooks。
Promise.resolve(1729).then(() => {
console.log(`eid ${ah.executionAsyncId()} tid ${ah.triggerAsyncId()}`);
});
// 产生:
// eid 7 tid 6
在这个示例中,添加任何实际的钩子函数启用了对 promise 的跟踪。
上面的示例中有两个 promise;由 Promise.resolve()
创建的 promise 和调用 then()
返回的 promise。
在上面的示例中,第一个 promise 得到 asyncId
6
,后者得到 asyncId
7
。
在执行 then()
回调期间,我们在 asyncId
7
的 promise 上下文中执行。
此 promise 由异步资源 6
触发。
promise 的另一个微妙之处是 before
和 after
回调仅在链式 promise 上运行。
这意味着不是由 then()
/catch()
创建的 promise 不会触发 before
和 after
回调。
更多详细信息请参见 V8 PromiseHooks API 的详细信息。