continuation-local-storage
NB: Git repo of truth is https://gitlab.com/northscaler-public/continuation-local-storage; all others are mirrors.
Overview
This module provides a means to store information along the entirety of a single Node.js asynchronous call chain, or "continuation".
It is equivalent to a Vert.x Context, and similar to ThreadLocal
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.
Use
There three flavors to choose from, based on either
-
cls-hooked
, -
zone.js
, or -
AsyncLocalStorage
(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
orzone.js
itself. The consuming codebase must install the library (or libraries) that it needs.
zone.js
If you are using ZoneJsContext
:
- You must
npm install zone.js
yourself. - You must
require('zone.js/dist/zone-node')
at the right time for your application.
See zone.js
's documentation for more information.
cls-hooked
If you are using ClsHookedContext
:
- You must
npm install cls-hooked
yourself.
AsyncLocalStorage
If you are using AsyncLocalStorage
:
- Your Node.js version must be
>=12.17.0
. - If you're using
setTimeout
,Promise.resolve
orPromise.reject
within yourrun
call, you must ensure that theautodispose
option is set tofalse
(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.
API
The basic API of these Context
s is straightforward.
Once you get the Context
(via require
or import
), these are the methods you'll use:
Factory method
Context(key)
:
Retrieves a context with the given key as a string (Symbol
ic names are a todo).
Instance methods
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.
Example
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.0
Context().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'
})