1.5 任务
在 ES6 中,有一个新的概念建立在事件循环队列之上,叫作任务队列 (job queue)。这个概念给大家带来的最大影响可能是 Promise 的异步特性(参见第 3 章)。
遗憾的是,目前为止,这是一个没有公开 API 的机制,因此要展示清楚有些困难。所以我们目前只从概念上进行描述,等到第 3 章讨论 Promise 的异步特性时,你就会理解这些动作是如何协调和处理的。
因此,我认为对于任务队列最好的理解方式就是,它是挂在事件循环队列的每个 tick 之后的一个队列。在事件循环的每个 tick 中,可能出现的异步动作不会导致一个完整的新事件添加到事件循环队列中,而会在当前 tick 的任务队列末尾添加一个项目(一个任务)。
这就像是在说:“哦,这里还有一件事将来 要做,但要确保在其他任何事情发生之前就完成它。”
事件循环队列类似于一个游乐园游戏:玩过了一个游戏之后,你需要重新到队尾排队才能再玩一次。而任务队列类似于玩过了游戏之后,插队接着继续玩。
一个任务可能引起更多任务被添加到同一个队列末尾。所以,理论上说,任务循环 (job loop)可能无限循环(一个任务总是添加另一个任务,以此类推),进而导致程序的饿死,无法转移到下一个事件循环 tick。从概念上看,这和代码中的无限循环(就像 while(true).. )的体验几乎是一样的。
任务和 setTimeout(..0) hack 的思路类似,但是其实现方式的定义更加良好,对顺序的保证性更强:尽可能早的将来。
设想一个调度任务(直接地,不要 hack)的 API,称其为 schedule(..) 。考虑:
console.log( "A" ); setTimeout( function(){ console.log( "B" ); }, 0 ); // 理论上的"任务API" schedule( function(){ console.log( "C" ); schedule( function(){ console.log( "D" ); } ); } );
可能你认为这里会打印出 A B C D ,但实际打印的结果是 A C D B 。因为任务处理是在当前事件循环 tick 结尾处,且定时器触发是为了调度下一个事件循环 tick(如果可用的话!)。
在第 3 章中,我们将会看到,Promise 的异步特性是基于任务的,所以一定要清楚它和事件循环特性的关系。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论