Local storage for asynchronous Node.js call stacks, similar to thread-local storage in multithreaded platforms
continuation-local-storageThreadLocal from Java, .NET, and other, similar platforms.Contexts allow you to place information in a continuation-local storage space so that it's available all the way up & down an asynchronous call stack so that you can set & get that information as necessary.
cls-hooked,zone.js, orAsyncLocalStorage (requires Node.js >= 12.17.0).Use whichever one you want to; the Context API is the same:
Run code in a context: Context().run(() => { / your code here */ }, { your: 'context', values: 'here' })
* Set a value in a context: Context().set('name', 'value')
* Get a value from a context: Context().get('name')
Using more than one implementation should work, but is not officially supported.
Try to stick with just one provider in your app.
>IMPORTANT:
> In order to minimize transitive dependencies in your application, this module does _not_ require cls-hooked or zone.js itself.
> The consuming codebase must install the library (or libraries) that it needs.
ZoneJsContext:npm install zone.js yourself.require('zone.js/dist/zone-node') at the right time for your application.See zone.js's documentation for more information.
ClsHookedContext:npm install cls-hooked yourself.AsyncLocalStorage:>=12.17.0.setTimeout, Promise.resolve or Promise.reject within your run call, you must ensure that the autodispose option is set to false (the default) in order to make the values available in those places.See this project's package.json devDependencies section for the versions of cls-hooked and zone.js was built against and try to install compatible ones.
Contexts is straightforward.Context (via require or import), these are the methods you'll use:Context(key):Retrieves a context with the given key as a string (Symbolic names are a todo).
run(fn, values, opts):
Runs a given function within the Context, making any values, an Object, available. opts currently includes only autodispose and is true by default.
set(key, value)
Sets the given value at the given key.
get(key)
Gets the value at the given key.
dispose()
It's not a bad idea to dispose of the Context when you know you're done with it, but it's not strictly required.
The run method defaults to manual disposal, but if you observe memory leaks, this would be the first thing to check.
javascript
const { ClsHookedContext: Context } = require('@northscaler/continuation-local-storage') // prerequisite: npm install --save cls-hooked
// or: const { ZoneJsContext: Context } = require('@northscaler/continuation-local-storage') // prerequisite: npm install --save zone.js
// or: const { AsyncLocalStorageContext: Context } = require('@northscaler/continuation-local-storage') // prerequisite: Node.js >= 12.17.0Context().run(
// this is the function that will be run in inside the Context
() => { // uses the default context; pass a string name for a custom context
// Do whatever you want here.
// Context values are accessible anywhere in the sync or async call stack:
const foo = Context().get('foo') // returns 'bar'
// You can set & get values with:
Context().set('baz', 'snafu')
const baz = Context().get('baz') // returns 'snafu'
},
// these are your contextual values available in the async call stack
{
foo: 'bar' // puts the value 'bar' into the context at key 'foo'
})
``