Cloudflare Workers 提供了 Node.js AsyncLocalStorage ↗ API 子集的实现,用于创建在异步操作过程中保持一致的内存存储。
import { AsyncLocalStorage } from "node:async_hooks";
const asyncLocalStorage = new AsyncLocalStorage();new AsyncLocalStorage(): AsyncLocalStorage- 返回新的
AsyncLocalStorage实例。
- 返回新的
-
getStore(): any- 返回当前 store。若在调用
asyncLocalStorage.run()初始化的异步上下文之外调用,则返回undefined。
- 返回当前 store。若在调用
-
run(storeany, callbackfunction, ...argsarguments): any- 在上下文内同步运行函数并返回其返回值。在回调函数外部无法访问 store。在回调内创建的任意异步操作均可访问 store。可选的
args会传递给回调函数。若回调函数抛出错误,run()也会抛出该错误。
- 在上下文内同步运行函数并返回其返回值。在回调函数外部无法访问 store。在回调内创建的任意异步操作均可访问 store。可选的
-
exit(callbackfunction, ...argsarguments): any- 在上下文外同步运行函数并返回其返回值。此方法等效于以
store值为undefined调用run()。
- 在上下文外同步运行函数并返回其返回值。此方法等效于以
-
AsyncLocalStorage.bind(fn): function- 捕获调用
bind()时的当前异步上下文,并返回一个在进入该上下文后调用传入函数的函数。
- 捕获调用
-
AsyncLocalStorage.snapshot(): function- 捕获调用
snapshot()时的当前异步上下文,并返回一个在进入该上下文后调用给定函数的函数。
- 捕获调用
import { AsyncLocalStorage } from 'node:async_hooks';
const asyncLocalStorage = new AsyncLocalStorage();
let idSeq = 0;
export default {
async fetch(req) {
return asyncLocalStorage.run(idSeq++, () => {
// Simulate some async activity...
await scheduler.wait(1000);
return new Response(asyncLocalStorage.getStore());
});
}
};API 支持同时使用多个 AsyncLocalStorage 实例。
import { AsyncLocalStorage } from 'node:async_hooks';
const als1 = new AsyncLocalStorage();
const als2 = new AsyncLocalStorage();
export default {
async fetch(req) {
return als1.run(123, () => {
return als2.run(321, () => {
// Simulate some async activity...
await scheduler.wait(1000);
return new Response(`${als1.getStore()}-${als2.getStore()}`);
});
});
}
};当 Promise 被拒绝且拒绝未被处理时,异步上下文会传播到 'unhandledrejection' 事件处理器:
import { AsyncLocalStorage } from "node:async_hooks";
const asyncLocalStorage = new AsyncLocalStorage();
let idSeq = 0;
addEventListener("unhandledrejection", (event) => {
console.log(asyncLocalStorage.getStore(), "unhandled rejection!");
});
export default {
async fetch(req) {
return asyncLocalStorage.run(idSeq++, () => {
// Cause an unhandled rejection!
throw new Error("boom");
});
},
};import { AsyncLocalStorage } from "node:async_hooks";
const als = new AsyncLocalStorage();
function foo() {
console.log(als.getStore());
}
function bar() {
console.log(als.getStore());
}
const oneFoo = als.run(123, () => AsyncLocalStorage.bind(foo));
oneFoo(); // prints 123
const snapshot = als.run("abc", () => AsyncLocalStorage.snapshot());
snapshot(foo); // prints 'abc'
snapshot(bar); // prints 'abc'import { AsyncLocalStorage } from "node:async_hooks";
const als = new AsyncLocalStorage();
class MyResource {
#runInAsyncScope = AsyncLocalStorage.snapshot();
doSomething() {
this.#runInAsyncScope(() => {
return als.getStore();
});
}
}
const myResource = als.run(123, () => new MyResource());
console.log(myResource.doSomething()); // prints 123AsyncResource ↗ 类是 Node.js 异步上下文跟踪 API 的组成部分,允许用户创建自己的异步上下文。继承自 AsyncResource 的对象能够传播异步上下文,方式与 Promise 类似。
请注意,AsyncLocalStorage.snapshot() 和 AsyncLocalStorage.bind() 提供了更好的方式。AsyncResource 仅为与 Node.js 向后兼容而提供。
import { AsyncResource, AsyncLocalStorage } from "node:async_hooks";
const als = new AsyncLocalStorage();
class MyResource extends AsyncResource {
constructor() {
// The type string is required by Node.js but unused in Workers.
super("MyResource");
}
doSomething() {
this.runInAsyncScope(() => {
return als.getStore();
});
}
}
const myResource = als.run(123, () => new MyResource());
console.log(myResource.doSomething()); // prints 123-
new AsyncResource(typestring, optionsAsyncResourceOptions): AsyncResource- 返回新的
AsyncResource。重要的是,虽然 Node.js 的AsyncResource实现要求构造函数参数,但在 Workers 中并未使用这些参数。
- 返回新的
-
AsyncResource.bind(fnfunction, typestring, thisArgany)- 将给定函数绑定到当前异步上下文。
-
asyncResource.bind(fnfunction, thisArgany)- 将给定函数绑定到与此
AsyncResource关联的异步上下文。
- 将给定函数绑定到与此
-
asyncResource.runInAsyncScope(fnfunction, thisArgany, ...argsarguments)- 在与此
AsyncResource关联的异步上下文中,使用给定参数调用提供的函数。
- 在与此
-
Workers 提供的
AsyncLocalStorage实现有意省略对asyncLocalStorage.enterWith()↗ 和asyncLocalStorage.disable()↗ 方法的支持。 -
Workers 未实现 Node.js
AsyncLocalStorage实现所依赖的完整async_hooks↗ API。 -
Workers 未实现 Node.js 允许的、使用显式标识触发上下文创建
AsyncResource的能力。这意味着新的AsyncResource始终绑定到创建它的异步上下文。 -
使用
AsyncLocalStorage时,Thenable(暴露then()方法的非 Promise 对象)未完全支持。处理 thenable 时,请改用AsyncLocalStorage.snapshot()↗ 捕获当前上下文的快照。