javascript - 使用 Promise.race 和 setImmediate 确定 Promise 状态

标签 javascript node.js promise settimeout setimmediate

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 不同的内容。区分实际undefineddoSomething() 返回的值:

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/

相关文章:

node.js - 如何在 Mongoose 中使用 elemMatch 进行查询?

php - 在 AngularJS 应用程序中正确包含 WordPress 博客的策略

javascript - 开发一个 Chrome 扩展来覆盖自签名证书的 SSL 证书异常

javascript - Cors 和 header

javascript - Node.js中的两个if语句

angular - 在 Observable 中返回 promise

javascript - javascript中如何执行同步性

javascript - 判断一个元素是否有一个带有 jQ​​uery 的 CSS 类

javascript - Bootstrap Datepicker 与 IE8 - 对象不支持此属性或方法

javascript - 实现 Promise.all 和 Promise.settle 的混合