简介
在 Node.js 中,我们常常面临的问题是如何在异步处理中传递上下文 contex. 为此,有些库会提供一些解决方案:比如 cls-hooked
, async-local-storage
等等,其中较为流行的一个便是 continuation-local-storage
(CLS) 。其中 @varlog/continuation-local-storage
是 CLS 的一个扩展。本文将为大家介绍 @varlog/continuation-local-storage
的使用教程。
安装
你可以使用 npm 安装 @varlog/continuation-local-storage
。
npm install --save @varlog/continuation-local-storage
使用
像其他 npm 包一样使用
你可以像使用其他 npm 包一样引入:
var cls = require('@varlog/continuation-local-storage');
使用该包默认返回一个 cls.Namespace
实例。如果你是在控制台或浏览器内运行该包,因为浏览器和控制台不支持异步本地存储,你可以单独使用 cls-localstorage
包代替。
创建新的存储实例
你可以通过以下方法来创建新的存储实例:
var cls = require('@varlog/continuation-local-storage'); var nsp = cls.createNamespace('myNamespace');
在命名空间中运行函数
当你使用 CLS 时,你需要将异步的执行内容放入命名空间中,以保证异步操作有正确的本地存储上下文。
比如以下代码:
-- -------------------- ---- ------- --- --- - ---------------------------------------------- --- --- - ----------------------------------- ---------- -- - ---------------- ----------- ------------- -- - ------------------------------ -- ------ ---
该代码会打印出 myValue
。函数 nsp.run()
会将该函数中的所有操作都放在名为 myNamespace
的命名空间中。
在子函数中使用相同的命名空间
如果你需要在子函数中使用相同的命名空间,你可以通过如下代码相应地操作:
-- -------------------- ---- ------- --- --- - ---------------------------------------------- --- --- - ----------------------------------- -------- ---------- - ------------------------------ - ---------- -- - ---------------- ----------- ----------- ---
你可以在子函数中使用 nsp.get('myKey')
调用同一命名空间中的值。
嵌套命名空间
当你需要在代码中嵌套命名空间时,你可以使用如下方案:
-- -------------------- ---- ------- --- --- - ---------------------------------------------- --- ---- - ---------------------------- --- ---- - ---------------------------- ----------- -- - --------------- ------------------- ----------- -- - ----------------------------- -- ----------------- --- ---
上述代码中,我们实例化了两个名为 nsp1
和 nsp2
的命名空间。我们在内部嵌套,在 nsp1
中执行一个函数,这个函数中又在 nsp2
命名空间中执行了一个函数。在 nsp2
命名空间中,我们读取了父命名空间 nsp1
中的值。我们可以像这样嵌套多个自定义CL命名空间。
自动绑定
cls 将自动包装一个函数以自动传递上下文:
-- -------------------- ---- ------- --- --- - ---------------------------------------------- --- --- - ---------------------------------------- ---------- -- - ----- ---- - ------------------------- - ------------------------------------------- --- ------------ ---
你可以传递任意数量的参数和回调函数到中间件函数中。cls 将自动传递上下文和参数。
Async Hooks
cls 实例提供了三种异步钩子(即在异步函数调用期间自动将上下文绑定到回调函数)。
Timeout
你可以使用 setTimeout
和 setInterval
函数。timeout 钩子会自动拦截 setTimeout
和 setInterval
中的回调函数,并将其添加到命名空间。以下是使用 timeout 钩子的示例:
-- -------------------- ---- ------- ----- --- - ---------------------------------------------- ----- --- - ---------------------------------------- ---------- -- - ------------- -- - -- -- ----- ------------------------------- -- ------ --- ----------------- -------
timeout 钩子会将 setInterval
函数中的方法也绑定到当前命名空间。例如:
-- -------------------- ---- ------- ----- --- - ---------------------------------------------- ----- --- - ---------------------------------------- ---------- -- - -------------- -- - --------- ------------------------------- -- ------ --- ----------------- -------
Event Handlers
你也可以连接事件,把所有事件回调函数绑定到当前 CLS 命名空间。以下是使用 event handler 钩子的示例:
-- -------------------- ---- ------- ----- --- - ---------------------------------------------- ----- --- - ---------------------------------------- ---------- -- - ----- ------ - ----------------------- ---- -- ---- -- -------------------- ------------------------ ------------------- ------------- --- -- ------------------ ------------- -- - ----- --- - ------------------------------------- ---------------------------- ------------------- -- ------ ----------------- -------
在 http.createServer()
调用中插入 nsp.bindEmitter(server)
,可以将该事件回调函数绑定到命名空间中,在回调函数的 body 中,你可以访问命名空间中的任意变量。在当前 CLS 命名空间的范围内,我们可以为单个请求设置上下文。当然,在这种情况下,我们可以在进程范围内管理多个请求。
Promises
你可以将剪切 Promise
对象的 thenable 函数并将上下文绑定到 handler
上。
-- -------------------- ---- ------- ----- --- - ---------------------------------------------- ----- --- - -------------------------------------- ---------- -- - ----- ------- - ------------------- -------------------- -- - -- ---- -- ---- --- ------- ----- -- --- ------- ------------- ----------------------------------------- ---------------- --- -------------------- -- - ----------------------------------------- --- --- ---------------- --- ---
结论
@varlog/continuation-local-storage
是一个相对易于使用的 cls 包。 通过本文介绍的使用教程,应该可以方便地在应用中使用 CLS。 除非你已经有一套解决方案来处理上下文,否则硬编码上下文是有风险的。维护 CLS 上下文应该成为一个高优先级任务。
参考:
- https://github.com/othiym23/node-continuation-local-storage
- https://tray.io/blog/how-to-use-cls-in-node-to-maintain-request-context-across-your-whole-stack/
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/60066b5551ab1864dac66a19