异步钩子-异步上下文存储
Asynclocalstorage
此类创建通过异步操作保持一致的存储。
虽然你可以在 node:async_hooks
模块之上创建自己的实现,但 AsyncLocalStorage
应该是首选,因为它是一种高性能且内存安全的实现,涉及实现起来并不明显的重要优化。
以下示例使用 AsyncLocalStorage
构建一个简单的记录器,它为传入的 HTTP 请求分配 ID,并将它们包含在每个请求中记录的消息中。
1 | import http from 'node:http'; |
AsyncLocalStorage
的每个实例都维护一个独立的存储上下文。 多个实例可以安全地同时存在,而不会有干扰彼此数据的风险。
静态方法
新增于 18.16.0
AsyncLocalStorage.bind(fn)
fn
绑定到当前执行上下文的函数
返回 在捕获执行上下文中调用fn
的新函数
AsyncLocalStorage.snapshot()
返回 带有签名 (fn: (...args) : R, ...args) : R
的新函数
捕获当前执行上下文并返回一个参数为函数的新函数。每当调用返回的函数,都会在捕获的上下文中调用传入的函数:
1 | const asyncLocalStorage = new AsyncLocalStorage(); |
AsyncLocalStorage.snapshot() 可以代替 AsyncResource 用于简单的异步上下文跟踪目的,例如:
1 | class Foo{ |
实例方法
asyncLocalStorage.disable()
禁用 AsyncLocalStorage
的实例。 对 asyncLocalStorage.getStore()
的所有后续调用都将返回 undefined
,直到再次调用 asyncLocalStorage.run()
或 asyncLocalStorage.enterWith()
。
调用 asyncLocalStorage.disable()
时,将退出所有当前链接到该实例的上下文。
在可以对 asyncLocalStorage
进行垃圾回收之前,需要调用 asyncLocalStorage.disable()
。 这不适用于 asyncLocalStorage
提供的存储,因为这些对象与相应的异步资源一起被垃圾回收。
当 asyncLocalStorage
在当前进程中不再使用时使用此方法。
asyncLocalStorage.getStore()
返回当前存储。 如果在通过调用 asyncLocalStorage.run()
或 asyncLocalStorage.enterWith()
初始化的异步上下文之外调用,它将返回 undefined
。
asyncLocalStorage.enterWith(store)
转换为当前同步执行的剩余部分的上下文,然后通过任何后续异步调用持久保存存储。
示例1:
1 | const store = { id: 1 }; |
此转换将持续整个同步执行。 这意味着,例如,如果在事件处理程序中输入上下文,则后续事件处理程序也将在该上下文中运行,除非使用 AsyncResource
专门绑定到另一个上下文。 这就是为什么 run()
应该优于 enterWith()
的原因,除非有充分的理由使用后一种方法。
1 | const emitter = new EventEmitter() |
asyncLocalStorage.run(store, callback[, …args])
- store
any
- callback 回调函数
- …args 后续参数
在上下文中同步运行函数并返回其返回值。 在回调函数之外无法访问该存储。 在回调中创建的任何异步操作都可以访问该存储。
可选的 args
被传递给回调函数。
如果回调函数抛出错误,则 run()
也会抛出该错误。 堆栈跟踪不受此调用的影响,上下文已退出。
示例:
1 | const store = { id: 2 }; |
asyncLocalStorage.exit(callback[, …args])
- callback 回调函数
- …args 后续参数
在上下文之外同步运行函数并返回其返回值。 该存储在回调函数或回调中创建的异步操作中不可访问。 在回调函数内完成的任何 getStore()
调用将始终返回 undefined
。
可选的 args
被传递给回调函数。
如果回调函数抛出错误,则 exit()
也会抛出该错误。 堆栈跟踪不受此调用的影响,并且重新进入上下文。
示例:
1 | // Within a call to run |