是什么决定了使用 promises 或 setTimeout 的延迟函数的调用顺序?

What determines the call order of deferred function using promises or setTimeout?

延迟函数的执行,例如在自定义事件处理中,是 JavaScript 中的常见模式(参见 here 示例)。过去使用 setTimeout(myFunc,0) 是唯一的方法,但是现在有一个替代方法: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。我还希望非本地 promise 库在后台使用 setTimeout所以结果会和 Edge 一样。

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

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


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

ll 取决于 resolve() 的内部实现方式 - 可能您观察到 setTimeout(fn, 0) 和 Edge 实现之间的差异 setImmediate(fn)

请考虑文章 - 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/ and one more link - setImmediate method