console.log(`top level: ${executionAsyncId()} ${triggerAsyncId()}`);
const f = () => {
console.log(`f: ${executionAsyncId()} ${triggerAsyncId()}`);
};
f();
const g = () => {
console.log(`setTimeout: ${executionAsyncId()} ${triggerAsyncId()}`);
setTimeout(() => {
console.log(`inner setTimeout: ${executionAsyncId()} ${triggerAsyncId()}`);
}, 0);
};
setTimeout(g, 0);
setTimeout(g, 0);
在上述代码中,我们使用 setTimeout 模拟一个异步调用过程,且在该异步过程中我们调用了 handler 同步函数,我们在每个函数内都输出其对应的 Async ID 和 Trigger Async ID 。执行上述代码后,其运行结果如下。
top level: 1 0
f: 1 0
setTimeout: 7 1
setTimeout: 9 1
inner setTimeout: 11 7
inner setTimeout: 13 9通过上述日志输出,我们得出以下信息:
调用同步函数,不会改变其 Async ID ,如函数 f 内的 Async ID 和其调用者的 Async ID 相同。
同一个函数,被不同时刻进行异步调用,会分配至不同的 Async ID ,如上述代码中的 g 函数。
追踪异步资源
正如我们前面所说的,Async Hooks 可用于追踪异步资源。为了实现此目的,我们需要了解 Async Hooks 的相关 API ,具体说明参照以下代码中的注释。
const asyncHooks = require("async_hooks");// 创建一个 AsyncHooks 实例。
const hooks = asyncHooks.createHook({
// 对象构造时会触发 init 事件。
init: function(asyncId, type, triggerId, resource) {},
// 在执行回调前会触发 before 事件。
before: function(asyncId) {},
// 在执行回调后会触发 after 事件。
after: function(asyncId) {},
// 在销毁对象后会触发 destroy 事件。
destroy: function(asyncId) {}
});
// 允许该实例中对异步函数启用 hooks 。
hooks.enable();
// 关闭对异步资源的追踪。
hooks.disable();
我们在调用 createHook 时,可注入 init 、 before 、 after 和 destroy 函数,用于 追踪异步资源的不同生命周期 。
全新解决方案
基于 Async Hooks API ,我们即可设计以下解决方案,实现日志与请求记录的绑定,即 Trace ID 的全局绑定。
const asyncHooks = require("async_hooks");
const { executionAsyncId } = asyncHooks;// 保存异步调用的上下文。
const contexts = {};
const hooks = asyncHooks.createHook({
// 对象构造时会触发 init 事件。
init: function(asyncId, type, triggerId, resource) {
// triggerId 即为当前函数的调用者的 asyncId 。
if (contexts[triggerId]) {
// 设置当前函数的异步上下文与调用者的异步上下文一致。









