Promise.then工作执行顺序

时间:2017-04-24 15:34:14

标签: javascript promise

The spec says(第5段):

  

始终在单个作业队列中启动PendingJob记录   FIFO订单。该规范没有定义其中的顺序   多个作业队列得到服务。 ECMAScript实现可以   交织作业的PendingJob记录的FIFO评估   通过评估一个或多个PendingJob记录进行排队   其他工作队列。

这是否意味着在依赖于同步控制流的.then回调之前,我无法依靠提供给setTimeout的回调?

换句话说,我可以依赖以下打印one two



setTimeout(() => console.log('two'));
Promise.resolve().then(() => console.log('one'));




3 个答案:

答案 0 :(得分:4)

  

这是否意味着在依赖于同步控制流的.then回调之前,我无法依靠提供给setTimeout的回调?

是的,这意味着什么;规范没有要求这些实现以这种方式工作。

但实际上,我已经对其进行过测试的本地Promise支持的实现已经安排了then回调(来自PendingJobs队列的" microtask")完成" macrotask"在其他未决的macrotask之前安排它,即使在微任务之前调度挂起的macrotask时也是如此。 (setTimeout和事件是macrotasks。)

,例如,在我对其进行测试的环境中,这会可靠地输出ACB



console.log("A");
setTimeout(_ => console.log("B"), 0);
Promise.resolve().then(_ => console.log("C"));




但JavaScript规范并不需要它。

作为Bergi points out,对于用户代理环境,其微型任务和宏任务规范中的HTML5 spec covers this。但这仅适用于用户代理环境(如浏览器)。

例如,

Node并不遵循该规范的定义(尤其是因为它的计时器函数返回对象而不是数字),但Node也为我们提供了A,{上面的{1}},C,因为(感谢Benjamin Gruenbaum!)它在B队列之后但在任何计时器或I / O回调之前运行承诺解析。有关详细信息,请参阅his gist

答案 1 :(得分:2)

是的,这意味着什么 - 其他事件可能会在承诺回调之前触发。

不,这不会发生 - 虽然ECMAScript允许,但setTimeout spec没有。

答案 2 :(得分:0)

setTimeout并不意味着所提供的功能将在提供的时间之后执行。一旦延迟过去,它就会将函数添加到队列的末尾。

这实际上取决于你的承诺何时解决,以及两个陈述的执行。在您的示例中,setTimeout会在已解决的承诺之前将其回调添加到队列中,因此您可以期待one two