Node.js async_hooks追踪时为何出现无init记录的promise resolve事件
现象原因
这个问题是Node.js ES模块加载机制和async_hooks钩子启用时机共同导致的:
- 你使用了
.mjs后缀的ES模块规范编写代码,Node.js加载、执行ES模块的整个流程本身是基于Promise实现的。在你代码里的async_hooks.createHook(...).enable()语句执行之前,Node.js内部已经为模块加载流程创建了若干个Promise实例,asyncId为8的Promise就属于这类内部生成的Promise。 - async_hooks的事件监听只有在调用
.enable()方法后才会生效,所有在.enable()执行完成前就已经完成初始化的异步资源,它们的init事件不会被当前钩子捕获。但只要这些异步资源的后续生命周期事件(比如promiseResolve、before、destroy等)发生在钩子启用之后,依然会被钩子捕获到。 - 对应到你的输出里,asyncId=8的Promise初始化发生在async_hooks钩子启用之前,所以没有对应的init日志;而它的resolve动作发生在钩子启用之后,因此会输出
promise resolve 8的记录。
验证方法
你可以通过两种方式验证这个结论:
- 将代码改为CommonJS规范(后缀改为
.cjs,把import替换为require语句),CommonJS是同步加载机制,不会提前生成内部Promise,运行后就不会出现这类无init的resolve日志。 - 保持ES模块规范不变,在钩子启用后手动创建一个Promise并resolve,会看到这个手动创建的Promise会同时输出init和resolve的完整日志。
内容的提问来源于stack exchange,提问作者Haotian Chyi
相关产品推荐
相关产品推荐

