6

continuation-local-storage似乎被使用,也在 express 的上下文中。

然而,非常基本的用法对我不起作用,因为上下文完全丢失了!

var createNamespace = require('continuation-local-storage').createNamespace;
var session = createNamespace('my session');


async function doAsync() {
    console.log('Before getting into the promise: ' + session.get('test'));
    await Promise.resolve();
    console.log('*in* the promise: ' + session.get('test'));
}

session.run(() => {
    session.set('test', 'peekaboo');
    doAsync();
});

结果是:

$ node server_test.js 
Before getting into the promise: peekaboo
*in* the promise: undefined

我做错了什么还是 CLS 只是坏了?还是图书馆坏了?如果它不打算与 Promise 一起使用,是否还有其他概念可以作为 threadLocal 存储以正确的方式实现多租户?

4

2 回答 2

7

cls-hooked似乎工作正常,尽管该库(如上一个)是两年前最后一次更新的......

如果有人有其他更强大的方法来实现多租户的线程本地状态,请分享!

于 2019-06-25T09:32:40.510 回答
1

您试图在多个函数之间保持共享状态,然后异步执行。这是 JS 中非常常见的情况,语言本身为此提供了一种非常简单但功能强大的机制:您可以从内部函数访问来自外部函数的变量,即使外部函数已经执行完毕:

 (function closured() {
    let shared = { /*...*/ };

    function inner() {
      console.log( shared );
    }
    setTimeout(inner);
  })();

现在虽然这可行,但它不能很好地扩展到更大的应用程序:访问该状态的所有函数都必须在一个函数内部,因此该文件真的被炸毁了。您正在使用的库正在尝试解决这个问题,它们还使用闭包来维护异步调用中的状态:当您注册异步回调时,状态存储在函数中,然后回调本身被包装到恢复状态的回调中:

   let state;

   function setTimeoutWithState(cb, time) {
      const closured = state;
      setTimeout(() => {
        state = closured;
        cb();
      }, time);
  }

  state = 1;
  setTimeoutWithState(() => console.log(state), 1000);

  state = 2;
  setTimeoutWithState(() => console.log(state), 500);

现在库只需要以这种方式包装每个异步回调,然后您就可以轻松地维护状态,不是很好吗?可以肯定的是,但是向每个回调添加代码确实是有代价的(因为 JS 大量使用回调)。

于 2019-06-27T12:27:06.707 回答