JS MarcoTasks MicroTasks

在JS的event loop中,有两种任务队列microtasksmacrotasks

microtasks

  • process.nextTick
  • Promise
  • Object.observe
  • MutationObserver

macrotasks

  • setTimeout
  • setInterval
  • setImmediate
  • I/O(Ajax, fs)
  • UI渲染

在一个事件循环event loop的周期中,一个task应该从macrotask队列开始执行。当这个macrotask结束后,所有的microtasks将在同一个cycle中执行。

且在microtasks执行时还可以加入更多的microtask,然后一个一个的执行,直到microtask队列清空。

console.log('start')

const interval = setInterval(() => {
console.log('setInterval')
}, 0) setTimeout(() => {
console.log('setTimeout 1')
Promise.resolve()
.then(() => {
console.log('promise 3')
})
.then(() => {
console.log('promise 4')
})
.then(() => {
setTimeout(() => {
console.log('setTimeout 2')
Promise.resolve()
.then(() => {
console.log('promise 5')
})
.then(() => {
console.log('promise 6')
})
.then(() => {
clearInterval(interval)
})
}, 0)
})
}, 0) Promise.resolve()
.then(() => {
console.log('promise 1')
})
.then(() => {
console.log('promise 2')
})

event loop1:

macrotasks: [主程序代码]

microtasks: []

执行macrotasks队列,也即执行主程序代码,收集macro或micro的tasks

输出: 'start'

收集的macrotasks(下次循环的): [setInterval, setTimeout]

收集的microtasks(当前循环的): [Promise]

macrotasks队列执行完毕,这时候microtasks: [Promise]不为空,执行microtasks队列

输出: 'promise1'

输出 : 'promise2'

这时候microtasks为空

下次循环开始之前的队列状态

macrotasks: [setInterval, setTimeout]

microtasks: []

event loop2:

执行macrotasks队列

执行setInterval

输出:'setInterval',且收集setInterval到下次循环的macrotasks中

执行setTimeout

输出:'setTimeout 1',且收集Promise到当前循环的microtasks: [Promise]

由于当前循环的microtasks不为空,执行队列中的任务Promise

输出:'promise3'

输出: 'promise4'

收集setTimeout到下次循环的macrotasks中

这时候microtasks为空

下次循环开始之前的队列状态

macrotasks: [setInterval, setTimeout]

microtasks: []

event loop3:

执行macrotasks队列

执行setInterval

输出: 'setInterval',且收集setInterval到下次循环的macrotasks: [setInterval]中

执行setTimeout

输出: 'setTimeout2',且收集Promise到当前的microtasks: [Promise]

由于当前循环的microtasks不为空,执行队列中的任务Promise

输出: 'promise5'

输出: 'promise6'

清除定时器clearInterval,所以下次循环的macrotasks的setInterval被清除

下次循环开始之前的队列状态

macrotasks: []

microtasks: []

event loop4:

由于macrotasks为空,和microtasks为空,程序处于等待状态。

上面程序总的输出结果是

// event loop1
start promise 1
promise 2 // event loop2
setInterval
setTimeout 1 promise 3
promise 4 // event loop3
setInterval
setTimeout 2 promise 5
promise 6

总结

  • 一个循环开始的时候microtasks(大多情况)是空的,或者说当前循环的microtasks一开始是空的,在macrotasks执行完后可能不为空
  • microtasks要等到macrotasks队列执行完毕才会开始执行,且microtasks的任务在执行的过程中,是可以添加任务的,只要当前循环还未结束
  • 在当前循环中收集的macro任务是收集到下一个循环的macrotasks,而当前循环收集的micro任务是收集到当前microtasks中

最新文章

  1. 创业方向:O2O及移动社交 from 沈博阳
  2. .Net 揭密--JIT怎样运行你的代码
  3. 在Hadoop分布式文件系统的索引和搜索
  4. mysql之union
  5. angularJS--神奇的$scope
  6. DataTables获取表单输入框数据
  7. CSS3之背景色渐变
  8. Computational Geometry Template
  9. poj3642 Charm Bracelet(0-1背包)
  10. java 线程关闭小结(转)
  11. JS模式--装饰者模式(用AOP动态改变函数的参数)
  12. sed命令详解-应用篇
  13. 【JAVA零基础入门系列】Day3 Java基本数据类型
  14. Django中Form的基本使用
  15. router-link 返回上页 和 新窗口打开链接
  16. Flannel网络插件配置
  17. HTML 滚动条样式修改
  18. epoll的高效实现原理
  19. CVTE笔试题
  20. scala实现相邻两个元素挑换位置的代码,哈哈

热门文章

  1. python模块之datetime方法详细介绍
  2. eclipse链接Hadoop集群时报错Error:Call From xxx/xxx.xxx.xxx.xxx to hostname1:9000 failed on connection exception
  3. 【Linux】linux下vi命令大全
  4. 修改response,报错Cannot call getWriter(), getOutputStream() already called
  5. Response.Redirect 打开新窗口的两种方法
  6. mybatis-plus 异常 Invalid bound statement (not found)
  7. 如何配置阿里Maven镜像
  8. 彻底解决Android 应用方法数不能超过65K的问题
  9. elasticSearch 分布式安装
  10. ArcGIS10.1的安装问题