使用 continuation-local-storage 时如何解决承诺?

est*_*ani 6 javascript node.js promise continuation-local-storage

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

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

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();
});
Run Code Online (Sandbox Code Playgroud)

结果是:

$ node server_test.js 
Before getting into the promise: peekaboo
*in* the promise: undefined
Run Code Online (Sandbox Code Playgroud)

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

est*_*ani 7

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

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


Jon*_*lms 1

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

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

    function inner() {
      console.log( shared );
    }
    setTimeout(inner);
  })();
Run Code Online (Sandbox Code Playgroud)

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

   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);
Run Code Online (Sandbox Code Playgroud)

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