TL;DR : 已经解决的 Promise会在setImmediate
比赛中获胜吗?
背景:
有时你想知道一个 Promise 是否在没有等待它完成的情况下被解决。有一些旧的遗留技巧,例如util.inspect
用于获取内部状态并检查它是否包含字符串"<pending>"
。但是,更稳定的解决方案是使用Promise.race()
(非常小的)超时基本上等待您的未知承诺。
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
。如果需要,“超时承诺”当然可能返回不同于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 ms 的计时器保证一个已解决的承诺胜过计时器?
我已经尝试在数组中的承诺传递给p
之前和之后放置它并且它以两种方式工作,但我仍然担心它可能会随机运行或依赖于操作系统?或者等待一轮 I/O 是否足以保证任何已解决的 Promise 都会获胜?setImmediate
Promise.race
setImmediate
从文档中:
在 I/O 事件的回调之后安排回调的“立即”执行
编辑:
我发现即使这个“似乎”也有效:
const result = await Promise.race([p, new Promise(resolve => resolve(PENDING))]);
甚至是这个:
const result = await Promise.race([p, Promise.resolve(PENDING)]);
但是,这里的顺序很重要。如果p
已解决并且在超时承诺之前,它将获胜,但如果它在数组中的超时承诺之后,它将失败。p
但问题是一样的:如果已经解决,这种方法是否保证让胜利?