【问题标题】:What determines the call order of deferred function using promises or setTimeout?什么决定了使用 Promise 或 setTimeout 的延迟函数的调用顺序?
【发布时间】:2016-04-21 03:17:06
【问题描述】:

延迟函数的执行,例如在自定义事件处理中,是 JavaScript 中的一种常见模式(例如,参见 here)。过去,使用 setTimeout(myFunc,0) 是唯一的方法,但是有了 Promise,现在有了另一种选择:Promise.resolve().then(myFunc)

我曾假设这些几乎可以做同样的事情,但是在处理包含自定义事件的库时,我想我会发现是否存在差异,因此我将以下块放入节点:

var logfn=function(v){return function(){console.log(v)}};

setTimeout(logfn(1),0);
Promise.resolve().then(logfn(2));
logfn(3)();

我原本希望在控制台上看到 3、1、2,但我看到的是 3、2、1。所以换句话说,Promise 不等同于使用 setTimeout,而是首先出现在块中。至少在节点中。

我在 Chrome 和 Firefox 中重复了测试,结果相同,但是在 Edge 中,结果为 3、1、2。我还希望非本地承诺库在后台使用 setTimeout,所以结果相同作为边缘。

是什么决定了这些调用的解决顺序?这些不同的环境使用什么模型来确定执行顺序?以上任何一项是否代表标准或非标准行为?

PS 我绝对不建议依赖任何这种保持一致,我只是好奇。


在下面给出的答案为我指明了正确的方向之后,正如下面评论中简要提到的那样,我在出色的 article by Jake Archibald 中找到了完整的答案(示例与我上面的代码几乎相同),我认为我会在这里加起来,而不是把它埋在评论中。

【问题讨论】:

  • FWIW,没有什么是保证异步执行的任何特定顺序。你不应该首先尝试依赖执行顺序。这使得这个问题成为关于实现细节的有趣讨论,但实际上没有实际意义。
  • 也许吧,但我倾向于发现我的编码改进得越多,我就越了解它是如何联系在一起的,即使是间接的。在挖掘了下面的答案之后,我还几乎完全找到了我上面的示例以及完整的解释here。鉴于所有这些,我绝对可以看到特定情况下推送到微任务或宏任务队列可能是合适的,但请注意,当只有宏任务可用时,您需要确保没有任何东西被破坏

标签: javascript node.js events settimeout es6-promise


【解决方案1】:

将取决于resolve() 的内部实现方式——您可能会观察到setTimeout(fn, 0)setImmediate(fn) 的Edge 实现之间的区别

请考虑文章 - http://www.mattgreer.org/articles/promises-in-wicked-detail/ 以及 resolve 方法的实现方式。

function resolve(value) {
    // force callback to be called in the next
    // iteration of the event loop, giving
    // callback a chance to be set by then()
    setTimeout(function() {
        callback(value);
    }, 1);
}

比一些解释可以在priority between setTimeout and setImmediate找到

来自 Microsoft 文档 - https://developer.microsoft.com/en-us/microsoft-edge/platform/documentation/dev-guide/performance/efficient-script-yielding/ 和另一个链接 - setImmediate method

【讨论】:

  • 感谢您提供文章链接和对setImmediate 的引用,这对我来说是新的。向上查找使我找到了 polyfill setImmediate,这导致了先前的 stackoverflow 答案,关于 microtask and macrotask event queue 之间的差异似乎可以解释正在发生的事情。我猜 Chrome 等人使用微任务事件队列来实现在宏任务队列中使用“setTimeout”的承诺。 Edge 或许没有这样的区别。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-01-07
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多