](https://codecov.io/gh/dimichgh/async-local)
async_hooks based local storage aka thread-local concept in java world.
The module provides a single layer of local storage for async flow, which is more than enough for a big platform.
npm install async-local -S
const AsyncLocal = require('async-local');
const express = require('express');
const app = express();
app.use((req, res, next) => {
AsyncLocal.run(next);
});
const AsyncLocal = require('async-local');
console.log(AsyncLocal.get('foo')); // >>> undefined
AsyncLocal.set('foo', 'bar'); // >>> throw error if no context is setup
AsyncLocal.run(ctx => {
AsyncLocal.set('foo', 'bar');
// or
ctx.set('foo', 'bar');
const promise = Promise.resolve();;
AsyncLocal.run(ctx => {
console.log(ctx.get('foo')); // >>> bar
console.log(AsyncLocal.get('foo')); // >>> bar
AsyncLocal.set('foo', 'qaz');
console.log(ctx.get('foo')); // >>> qaz
console.log(AsyncLocal.get('foo')); // >>> qaz
// promise preserves current context for the caller
promise.then(() => {
console.log(ctx.get('foo')); // >>> qaz
console.log(AsyncLocal.get('foo')); // >>> qaz
});
});
// promise preserves current context for the caller
promise.then(() => {
console.log(ctx.get('foo')); // >>> bar
console.log(AsyncLocal.get('foo')); // >>> bar
});
});
There are some edge cases when context is not preserved in async flow. For such cases, it makes sense to bind context to the function or emitter explicitly.
const EventEmitter = require('events');
const emitter = new EventEmitter();
AsyncLocal.bindEmitter(emitter);
const origFn = () => {
console.log(AsyncLocal.get('foo')); // >>> bar
};
AsyncLocal.run(() => {
AsyncLocal.set('foo', 'bar');
const fn = AsyncLocal.bind(origFn);
fn();
})