All right, so let's look at an example. This is kind of the canonical example I like to use for async local storage. Let's imagine we have a function. You know, we have this export default function right here. This is the kind of the workers' way of exporting a function handler. We have this async fetch. We wanted to do something and eventually we want some logging to happen in here. So, you know, we have this log function that logs a message. You know, think about it essentially as just a console log, that kind of thing.
And what we want to do is define a request ID that gets logged with the message whenever it goes out. Now, kind of the traditional way of doing it before async local storage, the way we would have to do this is, you know, we'd come up with a request ID. So, here we're using the const ID equals crypto random UUID. And we actually have to plumb that ID through all the different functions that need it, or that end up in a log statement. So, here we have to modify do something and do something else to take that request ID and forward it on to log, even though the do something and do something else have, you know, don't do anything else with request ID itself. So, you know, this gets a bit complicated if these functions that you're passing this through are in some other library or some dependency in your code.
Or if they're, you know, or if they're doing complex asynchronous tasks, that kind of thing. It becomes kind of awkward to have to modify all of these functions just to pass this ID along in order to get it into the log statement. So, what if there was a way that we could just say, here's the ID, whenever log runs, use this ID, but not have to be forced to pass that along through all the different layers of functions and stuff that we want to call. And that is what async local storage gives us, allows us to do. With async local storage, we can create this, this holder, this, you know, request ID equals new async local storage, this is container. And we can specify in our fetch handler that, hey, we want to run with this value, in this case, it's our request ID, it's random UUID. We want to run this code with that value set. Right? And those, you know, what changes here to do something and do something else, don't have to know anything about the request ID at all. They don't have to pass it along, except as a, as an argument. When log is called, it doesn't actually, it doesn't have to tell it, okay, what request ID are you running under? When log is called, when log is invoked, it will go to that container, that async local storage container, and just say, hey, get the value that's currently set for this when I'm running right now. So it's going to give us a really simple way of just kind of, hey, store this value later on in some other layer, we want to get the value. And notice that we're doing this past awaits. So this is happening asynchronously across multiple steps of the, of a promise branch. So, you know, it's, it makes it a lot easier, especially if these do something and do something else functions are coming from some dependency that you have no control over that you actually can't modify this way. You can actually set that context and retrieve it later without making any modifications to the, to everything else.
Comments