是否有可能在线程中有“线程”本地variables?
我想存储一个variables,在一个调用链中所有的栈帧(自顶向下)共享。 很像Java或C#中的ThreadLocal。
我find了https://github.com/othiym23/node-continuation-local-storage,但它保留了所有我的用例的上下文,似乎你必须修补你正在使用的库来使本地存储,意识到这对我们的代码基本是或多或less是不可能的。
Node中是否真的没有其他选项可用? 可以使用域,堆栈跟踪或类似的东西来获取当前调用链的句柄(id)。 如果这是可能的,我可以写我自己的线程本地实现。
对的,这是可能的。 托马斯·沃森(Thomas Watson)在NodeConf 2016年奥斯陆节点(NodeConf)上发表了他的Instrumenting Node.js
它使用Node.js跟踪 – AsyncWrap (它最终应该成为公共节点API的一个非常成熟的部分)。 您可以在开源的Opbeat Node代理中看到一个例子,或者更好的办法是查看对话幻灯片和示例代码 。
TLS在一些普通的单线程程序使用全局variables的地方使用,但是在multithreading的情况下这是不合适的。
由于JavaScript没有暴露的线程,全局variables是对你的问题最简单的答案,但使用一个是不好的做法。
您应该使用闭包:只需将所有asynchronous调用包装到一个函数中,然后在其中定义variables。
闭包中创build的函数和callback
(function() ( var visibleToAll=0; functionWithCallback( params, function(err,result) { visibleToAll++; // ... anotherFunctionWithCallback( params, function(err,result) { visibleToAll++ // ... }); }); functionReturningPromise(params).then(function(result) { visibleToAll++; // ... }).then(function(result) { visibleToAll++; // ... }); ))();
在闭包之外创build的函数
如果你需要你的variables在请求范围内没有定义的函数中可见,你可以创build一个上下文对象,并将其传递给函数:
(function c() ( var ctx = { visibleToAll: 0 }; functionWithCallback( params, ctx, function(err,result) { ctx.visibleToAll++; // ... anotherFunctionWithCallback( params, ctx, function(err,result) { ctx.visibleToAll++ // ... }); }); functionReturningPromise(params,ctx).then(function(result) { ctx.visibleToAll++; // ... }).then(function(result) { ctx.visibleToAll++; // ... }); ))();
使用上面所有在c()
调用的函数的方法获取对同一个ctx
对象的引用,但对c()
不同调用有自己的上下文。 在典型的用例中, c()
将是你的请求处理程序。
绑定上下文到this
你可以通过Function.prototype.call
调用它们,将你的上下文对象绑定到被调用的Function.prototype.call
:
functionWithCallback.call(ctx, ...)
…用Function.prototype.bind
创build新的函数实例:
var boundFunctionWithCallback = functionWithCallback.bind(ctx)
…或使用蓝鸟的.bind
类的诺言效用函数
Promise.bind(ctx, functionReturningPromise(data) ).then( ... )
其中的任何一个都会使ctx在你的函数中可用,如下this
:
this.visibleToAll ++;
…但是它并没有比传递上下文有真正的优势 – 你的函数仍然需要注意通过this
传递的上下文,如果你没有上下文,你可能会意外地污染全局对象。
现在,我最初问这个问题已经有一年多的时间了,最后看起来我们有一个工作解决scheme,以Node.js 8中的Async Hooks的forms出现。
https://nodejs.org/api/async_hooks.html
API仍然是实验性的,但即使如此,看起来已经有一个在本地使用这个新API的Continuation-Local-Storage分支。