Async context containers
What is the async-context-containers library?
Async context containers is a strongly-typed Typescript library that helps deeply nested async functions with getting context set higher up the call stack. It relies on cls-hooked, which is using the experimental node feature async-hooks.
Disclaimer!
As the async-hooks feature in Node.js is not yet stable, you should expect that your data could be undefined when you access it. Not that this happens that often (haven't tried it yet myself), but it is good practice to check for it anyways.
Concept
Context container:
A piece of context that can be shared at some point in your app,
eg. request context, config context, etc. You can access your context containers
state with the .get()
method, and set state with te .set()
method. These methods are exposed
by a ContainerContext
instance.
Context map (Typescript only): A context map is a Typescript interface that lays out a map of all your context containers. Here is an example:
// The properties describes the context state you can access with the .get() and .set() functions // Perhaps you want to share an Express request object longer down the call stack...
Context factory:
The object instance which is being used to load and create ContextContainer
instances.
Point of introduction: When dealing with async shared context, we are also dealing with the concept of time. Therefore, the context we would to provide our app with, can only be available after we introduce it at some point in the async call stack, and then only be available for the duration of that async call stack. This can be a little hard to grasp at first, but when you start writing some code with it, it should start to sink in.
Context provider:
When we want to introduce the context in the async call stack, we use the generateContextProvider()
method with some parameters that then can inserted into this function call...
withContext...contextProviders: ContextProvider.in;
They are pretty much just a type of middleware. You will learn more about this in the following Getting Started guide.
Getting started
Installation:
# With NPM npm install async-context-containers --save # Or with Yarn yarn add async-context-containers
The following usage examples uses Typescript as this library provides type-hinting...
Create a file for your context logic. Mine is called context.ts
context.ts:
// Import the factory creator function; // Define what your context looks like. Remember, keys are context names and the type describes// what state can be accessed // Example: config context // Export the Context factory object as you are going to use // this to access context around in your app.// Make sure to pass in your ContextMap as this will provide type hinting; // Create context provider for the config context..
Now we got our context boilerplate code sorted out, we will need to find where we want to introduce our context into our application. For demonstration purposes we will introduce the context at the starting point of our app, which of course also is a valid strategy. I do this in my index.ts
index.ts:
;; // Run applicationmain .then .catchconsole.logerr;
That is pretty much it. Feel free to play around with it all you like! If you find a bug, be sure to submit an issue on GitHub.