异步上下文的示例


以下是一个示例,其中包含有关 beforeafter 调用之间对 init 的调用的附加信息,特别是对 listen() 的回调将是什么样子。 输出格式稍微复杂一点,使调用上下文更容易看到。

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

require('net').createServer(() => {}).listen(8080, () => {
  // 让我们在记录服务器启动之前等待 10 毫秒。
  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 各自指定当前执行上下文的值;通过调用 beforeafter 来描述。

仅使用 execution 绘制资源分配图结果如下:

  root(1)
     ^
     |
TickObject(6)
     ^
     |
 Timeout(7)

TCPSERVERWRAP 不是这个图表的一部分,尽管它是调用 console.log() 的原因。

这就是为什么 TickObject 出现在输出中并且是 .listen() 回调的'父调用'。

可以用下图表示:

 bootstrap(1)
     |
     ˅
TCPSERVERWRAP(5)
     |
     ˅
 TickObject(6)
     |
     ˅
  Timeout(7)