cls-hooked的get()方法在ns.run()外部调用返回undefined问题
问题根因
cls-hooked 是基于异步钩子实现的上下文隔离库,它的上下文生命周期和ns.run()创建的作用域完全绑定:
- 调用
ns.run(callback)时,会新建一个独立的上下文压入当前执行栈,callback 内部、以及callback触发的整条同步/异步调用链上的代码,都处于这个上下文环境中,可以通过ns.get()拿到之前set的值。 - 一旦callback 同步执行完毕,这个上下文就会出栈销毁,外层不在该调用链上的代码,自然无法读取到上下文里存储的值,返回
undefined是符合设计预期的行为。
你的代码问题非常明确:你在namespace.run()的回调里执行完set操作,回调就直接结束退出上下文了,后面写在run外面的console.log(3,namespace.get('a'))、以及外层调用的someDeepNestedCallToGet(),根本不在run创建的上下文作用域内,当然拿不到值。
正确写法
cls-hooked的设计初衷是给单次异步调用链(比如每个HTTP请求)提供隔离的上下文存储,所有需要共享该上下文的逻辑,都必须放到ns.run()的回调调用链中执行,修改后的参考代码如下:
const http = require('http'); const createNamespace = require('cls-hooked').createNamespace const getNamespace = require('cls-hooked').getNamespace const sessionName = 'cats' const namespace = createNamespace(sessionName) function someDeepNestedCallToGet() { const session = getNamespace(sessionName); const baseObject = session.get('a') console.log('is working: ', baseObject); } http.createServer((req, res) => { // 每个请求进来创建一个独立的上下文 namespace.run(() => { // 在上下文内set值 namespace.set('a', 'value'); console.log('上下文内直接取值:', namespace.get('a')); // 所有需要读取该上下文值的逻辑,都在run回调内调用 someDeepNestedCallToGet(); console.log('서버 실행'); res.end('success') }) // 此处已退出上下文作用域,调用get永远返回undefined }).listen(8081, () => { console.log('8081번 포트에서 서버 대기중입니다.') });
补充说明
- 不要把cls-hooked的namespace当成全局变量容器用,它的核心价值是不同异步调用链之间的上下文隔离,比如同时进来10个HTTP请求,每个请求run里set的值互不干扰,不会出现串值问题。
- 如果你需要跨所有作用域的全局存储,直接用普通变量或者Map即可,不需要用cls-hooked。
内容的提问来源于stack exchange,提问作者MINWOO
相关产品推荐
相关产品推荐

