跳转到内容
搜索文档

AsyncLocalStorage

最后更新 查看 MarkdownAgent 设置

背景

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
  • run(storeany, callbackfunction, ...argsarguments) : any

    • 在上下文内同步运行函数并返回其返回值。在回调函数外部无法访问 store。在回调内创建的任意异步操作均可访问 store。可选的 args 会传递给回调函数。若回调函数抛出错误,run() 也会抛出该错误。
  • exit(callbackfunction, ...argsarguments) : any

    • 在上下文外同步运行函数并返回其返回值。此方法等效于以 store 值为 undefined 调用 run()

静态方法

  • AsyncLocalStorage.bind(fn) : function

    • 捕获调用 bind() 时的当前异步上下文,并返回一个在进入该上下文后调用传入函数的函数。
  • AsyncLocalStorage.snapshot() : function

    • 捕获调用 snapshot() 时的当前异步上下文,并返回一个在进入该上下文后调用给定函数的函数。

示例

Fetch 监听器

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());
    });
  }
};

多个 store

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");
		});
	},
};

AsyncLocalStorage.bind()AsyncLocalStorage.snapshot()

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 123

AsyncResource

AsyncResource 类是 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() 捕获当前上下文的快照。

这篇文档对您有帮助吗?