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 都会获胜?setImmediatePromise.racesetImmediate
从文档中:
在 I/O 事件的回调之后安排回调的“立即”执行
编辑:
我发现即使这个“似乎”也有效:
const result = await Promise.race([p, new Promise(resolve => resolve(PENDING))]);
甚至是这个:
const result = await Promise.race([p, Promise.resolve(PENDING)]);
但是,这里的顺序很重要。如果p已解决并且在超时承诺之前,它将获胜,但如果它在数组中的超时承诺之后,它将失败。p但问题是一样的:如果已经解决,这种方法是否保证让胜利?