考虑以下代码:
async function test(label) {
console.log(`BEFORE: ${label}`);
await waitForSomething(label);
console.log(`AFTER: ${label}`);
}
function waitForSomething(label) {
return {
then(onFulfilled) {
console.log(`FULFILL: ${label}`);
onFulfilled();
}
}
}
console.log('START');
test('A');
test('B');
console.log('END');
它给出以下输出:
START
BEFORE: A
BEFORE: B
END
FULFILL: A
FULFILL: B
AFTER: A
AFTER: B
我希望以同步方式在FULFILL A
之后立即触发AFTER A
,这将给出:
START
BEFORE: A
BEFORE: B
END
FULFILL: A
AFTER: A
FULFILL: B
AFTER: B
其 idea 是,我正在编写一个具有全局状态的库,我希望在用户编写的一系列同步调用中保持一致.由于多个链可能同时运行,因此我需要在呼叫链"恢复"之前运行一些代码.我知道乍一看这可能是一个奇怪或坏主意,但这是一个单独的问题.有办法做到这一点吗?
我想过用类似unwrap
方法的方法返回一个对象,该方法将触发代码,例如:
(await waitForSomething(label)).unwrap();
但这迫使用户在所有相关通话中使用unwrap()
,这很乏味.此外,他们可能会忘记这样做,并在不理解原因的情况下遇到意想不到的问题.
编辑:我将进一步阐述这背后的动机.基本上,这个 idea 是为了避免必须将状态参数一路向下传递到链并使其作为全局变量访问.
而不是做:
async function test(state) {
let input = await waitForUserInput();
doSomethingWith(state, input);
}
function doSomethingWith(state, input) {
// ...
}
我可以做:
async function test() {
let input = await waitForUserInput();
doSomethingWith(input);
}
function doSomethingWith(input) {
let state = MyLib.state;
// ...
}
这可以避免必须在test
触发的每个函数调用中携带state
.然而,由于其中一些函数是Deliverc,并且由于其中多个可以同时运行,并且由于每个根函数有不同的状态(例如test
),因此当Deliverc函数返回时,我需要将MyLib.state
设置为正确的值.同样,这是在库的上下文中:库为test
函数提供状态并运行它,但test
本身是由用户编写的.
编辑2:正如@user3840170所指出的那样,我需要的是https://github.com/tc39/proposal-async-context/,这只是提案的第二阶段.所以我想这目前是不可能的.