Node.js › Event Loop & Non-blocking IO
How would you use async_hooks (the lower-level predecessor to AsyncLocalStorage) to trace the lifecycle of asynchronous resources in Node.js?
AdvancedAnswer
async_hooks provides low-level lifecycle callbacks (init, before, after, destroy) fired whenever an asynchronous resource (a Promise, a Timeout, a TCP connection) is created and as it progresses through its lifecycle, letting you build tools that track the causal relationship between async operations (which operation triggered which) -- this is powerful but intricate to use correctly, which is why AsyncLocalStorage (built on top of async_hooks) is recommended for the common context-propagation use case, with raw async_hooks reserved for building specialized diagnostic or APM tooling.
const asyncHooks = require('node:async_hooks');
const hook = asyncHooks.createHook({
init(asyncId, type, triggerAsyncId) {
fs.writeSync(1, `Init: ${type}(${asyncId}) triggered by ${triggerAsyncId}\n`);
},
});
hook.enable();Real-world example An APM vendor's Node.js instrumentation library uses async_hooks internally to build a complete causal graph of every asynchronous operation within a request, powering the distributed tracing feature that shows exactly which downstream calls a given request triggered and in what order.