Как обойти обещания при использовании extension-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();
});
результаты в:
$ node server_test.js
Before getting into the promise: peekaboo
*in* the promise: undefined
Я сделал что-то совершенно не так или CLS просто сломан? Или библиотека сломана? Если он не предназначен для работы с обещаниями, существуют ли другие концепции, которые работают как хранилище threadLocal для правильной реализации многопользовательского режима?
2 ответа
Вы пытаетесь поддерживать общее состояние для нескольких функций, которые затем выполняются асинхронно. Это очень распространенный случай в 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 активно использует обратные вызовы).
cls-hooked, похоже, работает нормально, хотя библиотека (как и предыдущая) в последний раз обновлялась два года назад...
Если у кого-то есть какой-то другой более надежный способ реализовать локальное состояние потока для мультитенантности, пожалуйста, поделитесь!