TL;DR:已经解决的 promise 总是击败setImmediate
在比赛中?
背景:
有时您想知道 promise 是否已解决,而无需等待其完成。有一些旧的遗留技巧,例如使用 util.inspect
获取内部状态并检查它是否包含字符串 "<pending>"
。然而,更稳定的解决方案是使用 Promise.race()
基本上以(非常小的)超时等待您未知的 promise 。
const p = doSomething();
const result = await Promise.race([
p,
new Promise(resolve => setTimeout(resolve, 1))
]);
if (result) {
// p was resolved within 1 ms!
...
}
最多等待 1 毫秒才能获取 result
,然后它将包含 p
的解析值或undefined
。
如果需要,“超时 promise ”当然可能会返回与 undefined
不同的内容。区分实际undefined
从 doSomething()
返回的值:
const PENDING = Symbol.for('PENDING');
const result = await Promise.race([
p,
new Promise(resolve => setTimeout(() => resolve(PENDING), 1))
]);
if (result !== PENDING) {
...
}
现在我们可以从 doSomething()
获取解析值或独特的符号PENDING
.
现在回答我的问题。除了 setTimeout
,有一个setImmediate
基本上表现得像一个立即到期的计时器的函数;它只是在解决之前让事件循环继续下去。当在我的Promise.race
中使用它时上面的表达式,从经验来看它似乎有效,即,如果 p
已经解决了,它将击败 setImmediate
在一场比赛中,但我想知道是否有任何这样的保证 - 或者我是否应该使用 1 毫秒的计时器来保证已解决的 promise 击败计时器?
我尝试过输入 p
setImmediate
之前和之后传递给Promise.race
的数组中的promise它是双向的,但我仍然担心它可能会随机运行或依赖于操作系统?或者事实是setImmediate
等待一轮 I/O 足以保证任何已解决的 promise 都会获胜?
来自documentation :
Schedules the "immediate" execution of the callback after I/O events' callbacks
编辑:
我发现即使这样“似乎”也有效:
const result = await Promise.race([p, new Promise(resolve => resolve(PENDING))]);
或者实际上是这样的:
const result = await Promise.race([p, Promise.resolve(PENDING)]);
但是,这里的顺序很重要。如果p
已解决并且在超时 promise 之前,它将获胜,但如果它在数组中的超时 promise 之后,它将失败。
但问题是相同的:这种方法是否保证让 p
如果已经解决了就赢了?
最佳答案
考虑 Nodejs 中的以下代码
引用号。 https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/
setImmediate(() => console.log("setImmediate"));
setTimeout(() => console.log("setTimeout"));
process.nextTick(() => console.log("nextTick"));
Promise.resolve().then(() => console.log("Promise"));
console.log("sync");
输出:
您可以注意到顺序,这就是它如何按顺序执行。
sync
nextTick
Promise
setTimeout
setImmediate
为了回答您的问题,我们可以将代码包装在 Promises 中,如下所示:
(async function main() {
const result = await Promise.race([
new Promise(resolve => resolve("sync")),
new Promise(resolve => setImmediate(() => resolve("setImmediate"))),
new Promise(resolve => setTimeout(() => resolve("setTimeout"))),
new Promise(resolve => Promise.resolve().then(() => resolve("Promise"))),
new Promise(resolve => process.nextTick(() => resolve("nextTick"))),
]);
console.log({ result });
})();
由于sync函数是先执行的,所以会返回。
输出:
{ result: 'sync' }
您可以对上面的 Promise 之一进行评论,以查看哪一个首先得到解决。
关于javascript - 使用 Promise.race 和 setImmediate 确定 Promise 状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69462489/