Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

6 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

async-local-storage examples

AsyncLocalStorage is a Node.js API that provides a way of propagating the context of the current async operation through the call chain without the need to explicitly pass it as a function parameter. It is similar to thread-local storage in other languages.

Solving the Async Context Challenge in Node.js

The main idea of Async Local Storage is that we can wrap some function call with the AsyncLocalStorage#run call. All code that is invoked within the wrapped call gets access to the same store, which will be unique to each call chain.

Motivation -

Consider for example a standard web server that handles a couple of I/O operations. 

// server.ts
    router.get(
      path.join('/', 'user-details'), async (req, res) => {
          const accessToken = await extractAccessToken(req);
          const userDetails = await getUserDetails(accessToken);
          res.send(response);
      },
    );

// getUserDetails.ts
export async function getUserDetails(accessToken: string) {
    const isPermitted = await checkPermissionsOn(accessToken);
    if (!isPermitted) {
        throw new NotPermittedError('Not permitted');
    }

    const userDetalis = await queryUserDetails(accessToken);
    await logger.report(accessToken, `getUserDetails fetched with ${userDetalis}`);

    return userDetails;
}

In this example, the 'accessToken' param is contextual data associated with this request. It needs to be available in some or even all function scopes that are triggered within the 'user-details' route.

For each client request, we have an API call, a DB query, and another API call. The simplest way to have the accessToken available in the entire flow is to drill it down, from one function to another as a parameter.

But is it wise?

Do we really want to explicitly send accessToken from one function to another?
Should it be part of all functions' signatures in this chain?
Imagine a call chain where a parameter is passed from one function to another only to be used at the very end, should we drill down in that case?

Prop drilling is considered a bad practice in front-end development and to overcome it, there is the concept of state management and state management libraries. The basic idea of this concept is to have a 'store', an object that contains the application context.

Wouldn't it be nice to have something similar in Node?

Releases

Packages

Used by

Contributors

Languages