Promise.then 作业执行顺序 [英] Promise.then Job execution order

查看:25
本文介绍了Promise.then 作业执行顺序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

规范说(第 5 段):

来自单个作业队列的 PendingJob 记录总是在先进先出顺序.本规范没有定义顺序服务多个作业队列.ECMAScript 实现可能交织作业的 PendingJob 记录的 FIFO 评估排队评估一个或多个 PendingJob 记录其他作业队列.

The PendingJob records from a single Job Queue are always initiated in FIFO order. This specification does not define the order in which multiple Job Queues are serviced. An ECMAScript implementation may interweave the FIFO evaluation of the PendingJob records of a Job Queue with the evaluation of the PendingJob records of one or more other Job Queues.

这是否意味着我不能指望在其他同步控制流中提供给 .then 的回调在提供给 setTimeout 的回调之前被评估?

Does this mean I can't count on the callback supplied to .then being evaluated before a callback supplied to setTimeout in an otherwise synchronous control flow?

也就是说,我可以依赖下面的打印one two.

In other words, can I depend on the following printing one two.

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

推荐答案

这是否意味着我不能指望在其他同步控制流中提供给 .then 的回调在提供给 setTimeout 的回调之前被评估?

Does this mean I can't count on the callback supplied to .then being evaluated before a callback supplied to setTimeout in an otherwise synchronous control flow?

是的,就是这个意思;规范不要求实现以这种方式工作.

Yes, that's what it means; the spec doesn't require that implementations work that way.

但在实践中,我测试过的具有原生 Promise 支持的实现会在之后立即安排 then 回调(来自 PendingJobs 队列的微任务")在其他挂起的宏任务之前完成调度它的宏任务",即使挂起的宏任务在微任务之前被调度.(setTimeout 和事件是宏任务.)

But in practice, the implementations with native Promise support I've tested it on have scheduled the then callback (a "microtask" from the PendingJobs queue) immediately after finishing the "macrotask" that scheduled it, before other pending macrotasks, even when the pending macrotask was scheduled before the microtask. (setTimeout and events are macrotasks.)

例如,在我测试过的环境中,这会可靠地输出 ACB:

E.g., in the environments where I've tested it, this outputs A, C, B reliably:

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

但 JavaScript 规范不需要它.

But the JavaScript spec doesn't require it.

正如 Bergi 指出的,对于用户代理环境,HTML5 规范在其微任务和宏任务规范中涵盖了这一点.但这仅适用于用户代理环境(如浏览器).

As Bergi points out, for user agent environments, the HTML5 spec covers this in its specification for microtasks and macrotasks. But that's only applicable to user agent environments (like browsers).

Node 不遵循该规范的定义,例如(尤其是因为它的计时器函数返回对象,而不是数字),但 Node 也给了我们上面的 ACB,因为 (感谢 Benjamin Gruenbaum!)nextTick 队列之后但在任何计时器或 I/O 回调之前运行承诺解析.有关详细信息,请参阅他的要点.

Node doesn't follow that spec's definition, for instance (not least because its timer functions return objects, not numbers), but Node also gives us A, C, B above, because (thanks Benjamin Gruenbaum!) it runs promise resolutions after the nextTick queue but before any timer or I/O callbacks. See his gist for details.

这篇关于Promise.then 作业执行顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆