延迟执行函数(例如在自定义事件处理中)是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并且首先从块中出来。至少在Node中。
我在Chrome和Firefox中重复测试的结果相同,但是在Edge中它出现了3,1,2。我还希望非原生的promise库在引擎盖下使用setTimeout,所以会出现同样的问题作为边缘。
是什么决定了这些来电被解决的顺序?这些不同的环境使用什么模型来确定执行顺序?上述任何一种是否代表标准或非标准行为?
PS我真的没有暗示依赖任何一个这样的坚持,我只是好奇。在下面给出的答案指出了正确的方向,并且正如下面评论中简要提到的那样,我在一个优秀的article by Jake Archibald中找到了完整的答案(示例与上面的代码几乎相同),我虽然我在这里加起来而不是将其隐藏在评论中。
答案 0 :(得分:1)
ll取决于resolve()
内部实施的方式 - 您可能会发现setTimeout(fn, 0)
与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/以及另外一个链接 - setImmediate method