Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
May 28, 2022 02:02 am GMT

How to create a shared context between asynchronous calls in nodejs

Hello Everyone..!!!

As a javascript developer, even though you don't implement your own asynchronous functions very often, you are very likely to need to use them in your everyday project.

Typically there are two/three ways to deal with asynchronous functions.

  1. Callbacks
  2. Promises
  3. Async/Await (i.e Promises)

You can read more about these here.

Problem Statement

When you have a chain of asynchronous calls (callbacks or promises), how do you share a common context between all these calls?

Let's think of the following example.

You are writing a function called getCustomerOrders() that returns customer details along with his/her active orders. Inside that function you have to call asynchronous getCustomer() and asynchronous getOrders() where both of these function needs a customerId from in the Request.

shared context between asynchronous calls

Solution is simple right?

You just extract the customerId from the Request and pass it to both getCustomer() and getOrders() as function parameters.

const getCustomer = async (customerId: string): Promise<Customer> => {    return fetchCustomerFromApi(customerId);};

Yes, this is probably the best way that you share context between asynchronous calls. But do you know an alternative way to share context without passing as parameters?

AsyncLocalStorage

AsyncLocalStorage class of async_hooks module is released as part of Node.js 14.

As per the NodeJS official documentation

These classes are used to associate state and propagate it throughout callbacks and promise chains. They allow storing data throughout the lifetime of a web request or any other asynchronous duration. It is similar to thread-local storage in other languages.

In simple terms, this acts as a global variable that scoped to a particular asynchronous execution context.

Let's see AsyncLocalStorage in action

Let's see how we can refactor our getCustomerOrders() example to use AsyncLocalStorage

  1. First, import AsyncLocalStorage from async_hooks module.
import { AsyncLocalStorage } from "async_hooks";
  1. Next, you have to create instance from AsyncLocalStorage representing the data that you are going to share. In this example we are going to store the customerId.
const userAsyncLocalStorage = new AsyncLocalStorage<{ customerId: string }>();
  1. Now, you have to wrap the getCustomerOrders() function using AsyncLocalStorage.run function. This is where all the magic happens. As the first parameter to the run function, you can pass the data that you want to share.
userAsyncLocalStorage.run(    {      // customerId is read from the Request      customerId: "123456789",    },    async () => {      const customer = await getCustomer();      const orders = await getOrders();      // write data to Response       console.log({        customer,        orders,      });    }  );
  1. Finally, inside the getCustomer() and getOrders() you can retrieve customerId as below.
const getCustomer = async () => {    const { customerId } = userAsyncLocalStorage.getStore();    return fetchCustomerFromApi(customerId);}

That is the end of very basic application using AsyncLocalStorage.

Usage

Global state or variables are generally considered bad
as they make testing and debugging a lot harder. Therefor the pattern of using AsyncLocalStorage to share business data across multiple asynchronous calls (like we share customerId) is not recommended.

But AsyncLocalStorage pattern comes in handy when you develop/use APM Tools, which collect performance metrics.

This post explains how you can use AsyncLocalStorage to create a simple logger component.

Also NodeJS Frameworks like adonisjs uses AsyncLocalStorage extensively during the HTTP requests and set the HTTP context as the state.

You can read more about that here.

Appreciate your feedback and thank you very much for reading...!!


Original Link: https://dev.to/pahanperera/how-to-create-a-shared-context-between-asynchronous-calls-in-nodejs-4kim

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To