首先会发生啥:setTimeout 0 或 await Promise.resolve?

Posted

技术标签:

【中文标题】首先会发生啥:setTimeout 0 或 await Promise.resolve?【英文标题】:What happens first: setTimeout 0 or await Promise.resolve?首先会发生什么:setTimeout 0 或 await Promise.resolve? 【发布时间】:2019-06-05 03:08:51 【问题描述】:

我在 Node 和 Chrome 中看到了这种行为:

setTimeout(()=> console.log('timeout') , 0)
Promise.resolve().then(()=> console.log('promise') )
console.log('sync')

// output order:
// sync
// promise
// timeout

我的问题是,这是一致的行为吗?即,根据规范,在记忆/已解决的承诺上的 thenawait 总是在 setTimeout(fn, 0) 之前触发吗?

我想在类似以下的情况下使用它,如果我在我的承诺中有记忆的结果,则返回一件事,如果没有,则返回另一件事:

// somewhere during object initialization
this.resultingPromise = expensiveAsyncFunction()

// in a method called frequently
Promise.race([
    new Promise(resolve => setTimeout(() => resolve('default'), 0)),
    this.resultingPromise
])

【问题讨论】:

我会冒险说逻辑表明它会一直这样工作。我不知道这两种机制的内部工作原理,但是如果您设置一个计时器,创建一个已解决的承诺,然后输出到控制台,我希望看到您显示的内容。 console.log 立即工作,然后创建计时器并设置执行回调,并执行已解决的承诺。然后,将执行计时器回调,因为这将是下一步 - 计时器倒计时为零。这对我来说听起来很明智,我相信 JS 是明智的。 Jake Archibald 的这篇文章可能有助于澄清这种行为:jakearchibald.com/2015/tasks-microtasks-queues-and-schedules 基于 ***.com/a/36877743/5378743 总结点 2,您不能依赖订单。 感谢@ArnelleBalane,现在看到您在 kirill.buga 在下面的回答中发布了大致相同的内容。我想我应该阅读微/宏任务来理解这一点 【参考方案1】:

不能保证一个会先于另一个。如果你想保证执行顺序 - 使用 Promises。

【讨论】:

【参考方案2】:

Promise.resolve 将安排一个微任务,而 setTimeout 安排一个宏任务。并且微任务将在运行下一个宏任务之前运行。

关于事件循环的更多信息:https://www.youtube.com/watch?v=8aGhZQkoFbQ

有关事件循环的更多技术细节:https://www.youtube.com/watch?v=cCOL7MC4Pl0

【讨论】:

这有点启发性,将查看视频。发现这个答案***.com/a/25933985/1555158 暗示这个微/宏任务的概念可能在 WHATWG 标准中。 WHATWG 标准是否也是 es6 等的一部分?还是我弄错了,这家伙只指 WHATWG 指出 task queue 在该标准中 好的。会接受这个答案。从上面的@ArnelleBalane 链接 (jakearchibald.com/2015/tasks-microtasks-queues-and-schedules/…) 看来,ECMAScript 定义了“作业”的概念,而不是明确说明什么是微任务和宏任务。因此,即使实现具有这种一致的行为,我也找不到任何说明它必须始终具有上述执行顺序【参考方案3】:

所以你有 2 个异步等待状态,但请注意其中一个是恒定的,一个是变化的(变量)。超时设置在一个 XML 变量中,而承诺可能会永远持续下去。如果我很好地理解了你的问题,当你依赖的东西太长而太短时,除非你在其中一个上应用了一个常量,比如超时,那么最终可能会意外地运行更短(!)做好准备为此,而是出于代码安全原因而不是性能原因使用单片结构。

【讨论】:

对不起,我在那里看到了我的错误。编辑问题以在 setTimeout 中运行函数【参考方案4】:

据我了解,Promise 在调用堆栈中的优先级高于setTimeout,当然同步代码块将首先被执行。在这种情况下,是的,上面观察到的行为(按照同步代码块、promise.resolve 和 setTimeout 0 的顺序)应该是一致的。

【讨论】:

以上是关于首先会发生啥:setTimeout 0 或 await Promise.resolve?的主要内容,如果未能解决你的问题,请参考以下文章

首先会发生啥,MovieClip.onLoad() 或 Event.ENTER_FRAME?

JVM 终止时会发生啥?

在 vuejs 中使用 vue $nextTick 与 setTimeout 0 有啥区别

没有setTimeout 0,不理解堆栈

angular里的$setTimeout和原生的setTimeout有啥区别么

当 PayPal 订阅被取消或失败时会发生啥?