最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How to work around promises when using continuation-local-storage? - Stack Overflow

programmeradmin6浏览0评论

continuation-local-storage seems to be used, also in context of express.

Yet the very basic usage does not work for me, since the context is pletely lost!

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();
});

results in:

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

Have I done something pletely wrong or is the CLS simply broken? Or is the library broken? If it's not meant to work with promises, are there other concepts that work as a threadLocal storage to implement multi-tenancy in a proper way?

continuation-local-storage seems to be used, also in context of express.

Yet the very basic usage does not work for me, since the context is pletely lost!

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();
});

results in:

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

Have I done something pletely wrong or is the CLS simply broken? Or is the library broken? If it's not meant to work with promises, are there other concepts that work as a threadLocal storage to implement multi-tenancy in a proper way?

Share Improve this question asked Jun 25, 2019 at 9:04 estaniestani 26.6k2 gold badges102 silver badges83 bronze badges 4
  • Why not doAsync("peakaboo") ? And yes, the library does not seem to mention promises. – Jonas Wilms Commented Jun 25, 2019 at 9:16
  • @JonasWilms It's just a minimalistic example. The library is used in multi-tenancy context, in my real usecase it's getting documents from a mongo db, but I think this example is better suited to understand the problem. – estani Commented Jun 25, 2019 at 9:28
  • JavaScript itself provides a mechanism to access a shared state inside of different jobs, closures. Every library that tries to mimic that behaviour es with a huge cost, as it has to hook into every job. Thats why NodeJS deprecated its native hooks library as it was suffering from the same problems. That those libraries are not maintained indicates that they are also far from perfect. – Jonas Wilms Commented Jun 25, 2019 at 11:54
  • @JonasWilms can you extend as how closures can be used for such a case? What does node do now? How can some request related value be accessed from anywhere? – estani Commented Jun 27, 2019 at 10:22
Add a ment  | 

2 Answers 2

Reset to default 7

cls-hooked seems to be working fine, though the library (as the previous one) were last updated two years ago...

If someone has some other more robust way to implement a thread-local state for multi-tenancy please share!

You are trying to maintain a shared state across multiple functions which are then executes asynchronously. That is a very mon case in JS, and the language itself provides a very simple, yet powerful mechanism for that: You can access variables from an outer function from an inner function, even if the outer function already finished its execution:

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

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

Now while that works, it doesn't scale that well for larger applications: All functions accessing that state have to be inside of one function, and therefore that file gets really blown up. The libraries you are using are trying to resolve that, they also use closures to maintain the state across asynchronous calls: When you register an async callback the state is stored in a function, then the callback itself gets wrapped into a callback that restores the state:

   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);

Now the library just has to wrap every async callback that way, and then you can maintain the state easily, isn't that great? Well for sure it is, but adding code to every callback does have it's cost (as JS heavily utilizes callbacks).

发布评论

评论列表(0)

  1. 暂无评论