'AsyncLocalStorage losing context in response event handler
Here is a simple server that shows the issue:
const express = require("express");
const { AsyncLocalStorage } = require('async_hooks');
const als = new AsyncLocalStorage();
port = 3000;
class store {}
async function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function handle(res) {
console.log(`In handle, context is ${als.getStore() === undefined ? 'un' : ''}defined`);
res.on('close', () => {
if (!res.writableEnded) {
console.log(`In close, context is ${als.getStore() === undefined ? 'un' : ''}defined`);
}
});
await sleep(30000);
return 'Hello World';
}
createServer = () => {
const app = express();
app.get("/", async (req, res) => {
const ret = await als.run(new store(), async () => handle(res));
res.send(ret);
});
return app;
}
const app = createServer();
const server = app.listen(port, () => {
console.log(`I'm listening at http://localhost:${port}`);
});
With the server running, if you send a request - e.g. curl http://localhost:3000/ and then interrupt the curl command with ^C, the server shows:
[~/git/als-test] node server.js
I'm listening at http://localhost:3000
In handle, context is defined
In close, context is undefined
I'm guessing I need to use AsyncResource, but from the docs I'm not entirely sure how that would plug in to my example.
Solution 1:[1]
It seems the solution was very simple and did indeed involve AsyncResource. I just had to change:
res.on('close', () => {
if (!res.writableEnded) {
console.log(`In close, context is ${als.getStore() === undefined ? 'un' : ''}defined`);
}
});
to:
res.on('close', AsyncResource.bind(() => {
if (!res.writableEnded) {
console.log(`In close, context is ${als.getStore() === undefined ? 'un' : ''}defined`);
}
}));
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Horrendo |
