Skip to main content

about 3 years ago Syntax Podcast

AsyncLocalStorage + AsyncContext API

Wes Bos

Wes Bos Host

Scott Tolinski

Scott Tolinski Host

Topic 0 00:00

Transcript

Wes Bos

Reactathon,

Scott Tolinski

thing that allows you to

Scott Tolinski

other runtimes, other JavaScript runtimes. Yeah. When did this drop in Node? And

Scott Tolinski

Should we get on into it? We should. And I I will be taking the role of somebody who has not used it. I generally know what it is, but I will be trying to ask you some questions. So if if my question seem dumb

Scott Tolinski

in JavaScript. This is a server side JavaScript Or if they seem, like,

Scott Tolinski

On this Monday, HD Treat, we're gonna be talking about

Scott Tolinski

sync local storage in the async context API

Scott Tolinski

async local storage.

Scott Tolinski

Inside of Node specifically

Scott Tolinski

as well as what these these,

Scott Tolinski

Welcome to Syntex.

Scott Tolinski

So my name is Scott Cholinski. I'm a developer from Denver. And with me as always is Wes

Announcer

Open wide dev fans, get ready to stuff your face with JavaScript, CSS, node modules, barbecue tips, get workflow, breakdancing,

Scott Tolinski

your entire call stack for any given

Announcer

Monday. Monday. Monday.

Announcer

soft skill, web development, the hastiest, the craziest, the tastiest TS web development treats coming in hot. Here is Wes, Barracuda,

Wes Bos

talk, It's not a huge use case, but certainly will be handy. I could see this being handy for events in the browser. So, like, if you have async local storage I specifically have been using one called Hano Jet. Js, into every single one of those functions just to console log it. Right. I'm not using the show number anywhere else.

Scott Tolinski

off based, try to steer me in that direction because I'm interested in this stuff. And I I kinda have an idea of when you would use it, but I I wanna Really get the full picture here. So,

Scott Tolinski

Is it like are all these JavaScript run times aligned on this?

Announcer

key.

Scott Tolinski

piece of information that you want to share in that regard.

Scott Tolinski

My understanding is that this is a new API within JavaScript

Topic 1 08:46

Not in other runtimes yet, needs JS proposal

Wes Bos

and that will give you the cookies function internally will reach out

Wes Bos

So let's go into some actual examples

Wes Bos

in Next. Js

Wes Bos

you could pass data from 1 middleware to another because

Scott Tolinski

the actual JavaScript

Scott Tolinski

TC 30 9 proposal to to add this to the language. So you don't you don't see this as being a part of a lot of things until

Wes Bos

I'm assuming with Next. Js, clean it up if you do have that issue, though.

Wes Bos

every single function that needs it. You can simply just access it wherever it is that you need it. So I think we are starting to see This type of thing being implemented. Again, it's only 2 or 3 years old. I guess that is kind of long, but we're starting to see a lot of people glad to share, and we'll catch you later. Peace. Peace.

Topic 2 07:02

Alternative is passing context object with issues

Scott Tolinski

aren't using async local storage

Wes Bos

I don't want to like, why are we using just a node API? So that's why they're not like a stand alone.

Wes Bos

So the and

Wes Bos

but it doesn't work as soon as you Maybe there's a potential memory leak there. There is an exit method you can do that will explicitly Some foot guns. Having things globally available I have done a I did a little TikTok on it a couple of weeks ago, and then I talked about it in my And you want to be able to access the headers or the cookies, the level, you'll be able to access

Scott Tolinski

Are you raising your hand? I'm raising my hand. Oh, what's up? I would like I would just have a quick question. I wanna I just wanna interrupt. I wanted to get this before you moved on from this.

Scott Tolinski

Why would you say that most

Wes Bos

A lot of these frameworks are trying to within Next. Js. So if you have an action or a and then anywhere else I work to console. Log, I can simply just access it. In fact, I made a custom console log function, down the line, a middleware is a really good example where You might have a middleware that, like, populates your user.

Scott Tolinski

frameworks today in node

Wes Bos

new API

Scott Tolinski

context,

Wes Bos

a lot of frameworks these days, One of the reasons is that this is so this is a Node API.

Scott Tolinski

for

Wes Bos

anywhere down specifically, this API doesn't cause memory leaks, but it's just another thing to think about if you are referencing an object or value Has to then be past it, right? You might have context that like a top level, but what happens if you want it 7 levels deep in your data fetching library, right? You don't necessarily have access to So the async local storage will allow you to define a store and access it anywhere down. It's sort of like I kind of look at it as a closure variable. In JavaScript. If you have declare a variable inside of a function

Topic 3 14:22

Downside is hard to test code relying on external data

Wes Bos

that context

Wes Bos

is makes it kind of hard to test, right? Think about if you want to test a React component, Promise chaining each. If you use .then We have this problem in React and many other, and access the sync local search, right? You can see how that could be a bit of an issue. Yeah.

Wes Bos

And then it could cause a memory leak as well. Just like anything in JavaScript, if you are referencing something That is it.

Wes Bos

your function needs to reach into the ether and tracing console logs. That's where 98% of this type of thing is going to lie, where you need to be able to access it.

Topic 4 11:39

Example of logging show numbers without passing refs

Wes Bos

because You could grab it A cyclical surge is pretty cool. So we're gonna kind of run through what it is a function that calls another function, right? And that function will say, Okay, let's probably the most common use case is for logging and tracing of request IDs. Every single time you have a request come in, You can make a unique identifier for that request Boss, and Scott you're on the first one, you have a request ID and then the 2nd time within my route handler inside of a function

Wes Bos

the whole thing is garbage collected and you don't have to worry about it anymore.

Wes Bos

The API for it, you can stick anything you want in it. So it's not like local storage where it's a key value. It could be a variable,

Wes Bos

I can say, okay, well, I know that this happened on this request

Wes Bos

When the function starts and then when it's done, in the summarize it. We have a function but a store what context is. So when you have a function in JavaScript and you call that function. So like, let's say somebody's going to westboss.com.

Wes Bos

We put the show number in the synclical storage

Topic 5 02:13

Gaining momentum due to Async Context API proposal

Wes Bos

for something called the Async Context API, which does pretty much the exact same thing, which means that Or on this specific show parsing, you might be saying, well, can't you just stick a variable in memory? You know, just make a variable outside your function and reference that on every single time. The problem with that is if you're running 2 functions at once, when I was

Topic 6 05:00

Examples in SvelteKit and React

Scott Tolinski

the the prop flow of things inside of React. Right? Exactly.

Scott Tolinski

avoid that problem of having to pass props from child to child to child to child. You put something in the React context and are able to access it outside of the,

Wes Bos

what we're doing right now in a lot of use cases is we have a request object.

Wes Bos

And if you want something to be able to be accessed work on every single object.

Wes Bos

8 levels deep, but I don't want to have to manually pass it along

Wes Bos

within that function call so that any functions inside of it that reach out will be able to access it. So tracing.

Scott Tolinski

The other one might just be in general React context where, Let's say you wanted to

Scott Tolinski

essentially

Wes Bos

every single way, and we'll talk about the benefits and cons against that in just a sec as well. So those variables in memory are often shared and they're overriding each other. This will simply just make a store proposal gets pushed through. That's a good question. But, so Next. Js access to data that is in context.

Wes Bos

and access that store if you have multiple middlewares, it has been gaining a little bit of momentum recently because of a few reasons.

Topic 7 03:26

Example of passing context through nested functions

Wes Bos

fetch some excited to talk about it.

Wes Bos

all the way down. You know, a function calls a function that calls another function. If you ever want to share data between So obviously they polyfilled it and you can use it in Deno. But there is a proper,

Wes Bos

but that function might call another function. That function might call another function. Right.

Wes Bos

I'll have a route handler. That's a function, right? And that function will get a request and then we can send a response back from it. Right. And then in that handler, that increases memory usage. And eventually, you're going to run out of memory and your app will fall over. So server function or anything Find this useful because you can also, and then any function that is called anywhere down With a sync local storage, prop based languages where

Wes Bos

So any

Wes Bos

I might have people saw this in notes, Hey, that's actually kind of helpful.

Topic 8 15:55

Useful for browser events instead of passing data around

Wes Bos

An event that fires, So this dropped in Node 13. So meaning it's been around for 3 years already in Node.

Scott Tolinski

application and stuff using the the context. I don't need to rewrite things, but, like, it seems like that's, like, what I would want to do. Just throw it in a async local storage within my my server side hook.

Wes Bos

and be able to access that find a function somewhere else.

Scott Tolinski

Yeah. And then or somebody like you, sharing this. Awesome. Alright. Well,

Wes Bos

in sync context But that React component assumes that it has It's not being garbage collected. And every single time you make an object of people, balls. Hey, For some use cases,

Scott Tolinski

somewhere else. It feels like I want to do that in my

Wes Bos

be able to access it application wide. Sounds pretty neat. Exactly. Like it's similar to like a request object, right? Request comes in. You want to be able to access that data, then maybe an event.

Topic 9 04:25

Why frameworks don't use it yet for middleware

Scott Tolinski

you have like

Scott Tolinski

locals is just available, and everything that gets saved to locals is available. But it is passed through the function.

Scott Tolinski

In in Svelte kits, for instance, a request comes in

Scott Tolinski

Yeah. Or I wasn't gonna say React content. This is something different. This is, were you thinking React contacts? Is that what you were implying? Both those. I think you should go into both of them. So in middleware, typically, a request comes in maybe like an auth token or something. You validate that user, and then you pass that user information along. In SvelteKit, they do it through something called locals where in all of your request functions,

Topic 10 12:59

Can store anything - objects, maps, sets, timers

Wes Bos

Some. I guess sometimes it makes sense. Just pass that ID around. But if you want to be able to clear the timer, there's an API for starting it with existing data.

Wes Bos

the timer in another function.

Wes Bos

could be an object. A lot of times people use sets and maps because sets and maps have nice APIs to work with them. You can do whatever you want. You can stick timer IDs in there. Like, Let's say you start a timer in 1 function and then you want to be able to clear

Topic 11 06:30

Use case: populating user from database in middleware

Wes Bos

It's kind of just a spot where you stick anything you want. Anybody can stick anything on there, However,

Wes Bos

And so the request comes in.

Wes Bos

call it a context

Wes Bos

You populate the user, you get them from the database, and then you stick the whole user on the request object and you call next or you return it. And then the function that gets called next down the line will we'll have access to that because it's on the request and kind of the request object or a lot of frameworks You could just stick it sometimes if you reference something in JavaScript that is and the console log function won't reach into a link, async local storage, grab the show number, and then prepend the show number with the console log. So my console logs are not a huge mess.

Topic 12 10:18

Next.js uses it for cookies and headers

Wes Bos

and use it to access it anywhere down the line. So you could put a cookie in there. We've said you could use logging, and bring it down for that. That makes a lot of sense because you don't have to pass it along to every single function, and it's really nice. So instead of passing the data every single function that does want to be able to access the context I foresee us Seeing like best practices come out of this in the next year or so of like people, Oh, we used a sync local storage everywhere and the thing blew up. Or here's a couple of use cases. We did use sync local storage, and it worked out well for us. Very fascinating. Well, cool stuff, Wes. This is the type of stuff that I, personally, you know, wouldn't come across it if it wasn't

Wes Bos

of like, why would you ever want to use this as well as like, isn't this a bad idea into the sky, Grab the async local storage value down and return to you all the cookies. That's super nice because, again, you don't have to pass the headers and the cookies by its name, Only using a node API on on out from that. So running all the Syntax

Topic 13 02:38

Allows accessing context down call stack without passing refs

Wes Bos

let's understand is kind of a no go for a lot of them. I went into I was like, Okay, is this in Deno? And I literally found the thread where Ryan Dahl goes, This is cool. I can see where this would be helpful, which was on, like, next gen JavaScript frameworks.

Wes Bos

It will allow you to access context down the call stack. So before we get into any of these things, and .catch syntax instead of asyncawait, condense it. We have a function to You're going to have the same issues here where your test runner will have to mock So I think local storage. It's kind of like a bad name because it doesn't have anything to do with local storage.

Wes Bos

It doesn't have an API like local storage, really. It doesn't it's not like it's not like, oh, it's like it's like local storage, but you can async away to it. It's nothing like that.

Wes Bos

browser as well? you simply just import a function from Next. Js library called cookies. You run cookies and and why you might need it.

Topic 14 10:46

Use cases: request IDs, user prefs, logging

Wes Bos

episodes through the OpenAI API.

Wes Bos

one zero seven for show number 203. Right. But I don't want to pass the show number

Wes Bos

So why do I have to pass it in just for my own logging needs? Well, when you start off that initial request, you could just reach into a sync local storage, get the timer ID, Go ahead and clear it.

Wes Bos

You for middleware. Yeah. That's a great question. I think because it is a relatively you could just stick prefixed with the show number. And if there's an error,

Wes Bos

could query user preferences to add the speaker, Right? Like, there's probably 20 different functions that are running, and I want a console log running x, y, and z for show number when

Wes Bos

It's pretty nice for that type of stuff. I specifically

Wes Bos

and just be able to get your users preferences wherever it is that you want.

Topic 15 04:06

Current way is passing references down call stack

Wes Bos

you pass something along from function to function so that anybody that needs it anywhere down the line will be able to have access to it. Sound familiar? We have this problem.

Wes Bos

Where where have you seen this problem before? called deploy target ever. Oh, I see. So using

Wes Bos

the way to do it is you just pass some sort of reference or has implemented it. Cloudflare Workers has implemented it, and Next. Js uses it to be able to access cookies and headers The the call stack or any function that is then subsequently and everywhere? So let's explain. In client side JavaScript. Yeah, Yeah, exactly. Like, I have a couple of examples of, like, why would you ever want this of that event all of those function calls.

Wes Bos

Right now, They're just nicely You have like a that might overwrite each other, because if things happen out of order, then you get into real trouble those are some kind of use cases. I think in most cases, a closure variable, there is now a proposal in TC39 all the way down, It's not a very pure function a function that is called I want something to go from 1 level down will be able to essentially just reach into the thin air

Scott Tolinski

Middleware. So, basically have a context amongst Head on over to syntax.fm

Topic 16 13:33

Useful for promise chaining instead of passing data

Wes Bos

each piece of data that you get into a sync local storage and then when it's all done, values from the database, Will allow you to define and you no longer reference it, JavaScript will garbage collect it. However,

Wes Bos

Sometimes it's annoying to Yeah. You have to if you want like data shared between the 2, you have to like pass it. You have to return it from the then and then destructure it in the next then or you have to like, make a variable outside that's empty and then reach outside and update it right. So Wouldn't it be cool if that was just a feature we had in JavaScript user sessions, user login

Topic 17 16:43

Expect best practices to emerge over next year

Scott Tolinski

Or drop a review if you like this show.

Scott Tolinski

for a full archive of all of our shows.

Scott Tolinski

And don't forget to subscribe in your podcast player

Topic 18 15:00

Can also cause memory leaks if not cleaned up properly

Wes Bos

like a variable somewhere else you would think, oh, yeah, JavaScript will garbage collect it. You can run into an issue where I have like we have a function to

Topic 19 02:05

AsyncLocalStorage added in Node 13

Wes Bos

However, you got to think about, okay, well, And I was firing off 5 at a time and and it's really hard to type it. It's really hard to know what's available to yourself.

Share

Empowering developers for over 286197050937 milliseconds!