ashwanikumarjha
Wed Oct 02 2024
Async Local Storage in Node.js
• Provides us a way to store and manage context-specific data across asynchronous operations without needing to pass it explicitly through function arguments.
• Built on the
• We need to use
• Asynchronous operations initiated within this callback inherit that context.
• Each context created with
• Common use cases can be maintaining custom context in our web app (e.g., request data, user ID...) across multiple layers (controllers, services, etc.), can help us with tracing how a request propagates through different async functions.
• Automatically cleans up the context after the asynchronous operations are complete.
•
• Set a value:
• Get a value:
• Provides us a way to store and manage context-specific data across asynchronous operations without needing to pass it explicitly through function arguments.
• Built on the
async_hooks
module, which tracks asynchronous resource lifecycle events.• We need to use
asyncLocalStorage.run(store, callback)
to create a new context.• Asynchronous operations initiated within this callback inherit that context.
• Each context created with
asyncLocalStorage.run()
is unique and does not interfere with other contexts.• Common use cases can be maintaining custom context in our web app (e.g., request data, user ID...) across multiple layers (controllers, services, etc.), can help us with tracing how a request propagates through different async functions.
• Automatically cleans up the context after the asynchronous operations are complete.
•
run(store, callback)
: Creates a new context and runs the callback with the provided store (like a Map or a primitive value).• Set a value:
asyncLocalStorage.getStore().set('requestId', requestId);
• Get a value:
const requestId = asyncLocalStorage.getStore().get('requestId');
const http = require('node:http');
const { AsyncLocalStorage } = require('node:async_hooks');
const { v4: uuid } = require('uuid');
const asyncLocalStorage = new AsyncLocalStorage();
function logWithId(msg) {
const requestId = asyncLocalStorage.getStore();
console.log(`${requestId} - ${msg}`);
}
function serviceA() {
logWithId('Service A log');
}
function serviceB() {
logWithId('Service B log');
}
http.createServer((req, res) => {
const requestId = uuid();
asyncLocalStorage.run(requestId, () => {
logWithId('Request received');
serviceA();
serviceB();
logWithId('All services called');
res.end('Response sent');
});
}).listen(4040);
http.get('');
// Output:
<generated-request-id> - Request received
<generated-request-id> - Service A log
<generated-request-id> - Service B log
<generated-request-id> - All services called