0

我尝试async_hooks在 nodejs 中使用实验模块。

const Async = require('async_hooks');

const store = {};
const hook = Async.createHook({
    init: function (child, _, parent) {
        if (store[parent]) {
            store[child] = store[parent];
        }
    },
    destroy: function (id) {
        delete store[id];
    },
});
hook.enable();

let autoInc = 0;
let promise;
function run(index) {
    const asyncId = Async.executionAsyncId();
    if (!store[asyncId]) {
        store[asyncId] = { uuid: autoInc++ };
        console.log('ASYNC Created', store[asyncId]);
    } else {
        console.log('ASYNC Reuse', store[asyncId]);
    }
    
    if (!promise) {
        promise = Promise.resolve();
    }
    if (index < 1) {
        setTimeout(() => run(index+1), 0); // -> Version A
        // promise.then(() => run(index+1)); // -> Version B
    }
}

setTimeout(() => run(0), 0);
setTimeout(() => run(0), 0);

如果我尝试“版本 A”(带有 setTimout)我有这个输出:

ASYNC Created { uuid: 0 }
ASYNC Created { uuid: 1 }
ASYNC Reuse { uuid: 0 }
ASYNC Reuse { uuid: 1 }

但是,如果我尝试“版本 B”(带有承诺),我会得到以下输出:

ASYNC Created { uuid: 0 }
ASYNC Reuse { uuid: 0 }
ASYNC Created { uuid: 1 }
ASYNC Reuse { uuid: 0 }

第二个执行上下文附加到第一个执行上下文,因为“then”被附加在第一个上下文的承诺上。但这很成问题:我不能像 java 中的“ThreadLocal”那样使用它。你有解决方案吗?我可以创建第二个承诺来解决问题,但这对我来说不是一个可接受的解决方案。

问候。

4

1 回答 1

0

感谢 @Robert Kawecki 的图书馆 cls-hooked。我不明白为什么,但是这个库比 async_hook 方法工作得更好:

const CLS = require('cls-hooked');

const namespace = CLS.createNamespace('try-it');

let autoInc = 0;
let promise;
let allStores = [];
function run(index) {
    namespace.run(() => {
        const currentValue = namespace.get('id-context');
        if (currentValue === undefined) {
            namespace.set('id-context', autoInc++)
            console.log('namespace Created', namespace.get('id-context'));
        } else {
            console.log('namespace Reuse', namespace.get('id-context'));
        }

        if (!promise) {
            promise = Promise.resolve();
        }
        if (index < 1) {
            // setTimeout(() => run(index + 1), 0); // -> Version A
            // promise.then(() => run(index + 1)); // -> Version B
            setTimeout(() => {
                promise.then(() => run(index + 1));
            }, 10) // -> Version C
        }
    });
}

setTimeout(() => run(0), 0);
setTimeout(() => run(0), 0);

版本 A 和 C 说

namespace Created 0
namespace Created 1
namespace Reuse 0
namespace Reuse 1

版本 B 说:

namespace Created 0
namespace Reuse 0
namespace Created 1
namespace Reuse 1

所以我认为这个库的承诺被重写以解决问题,但感谢您的解决方案。

于 2021-03-27T23:45:26.397 回答