
WX20200111-164807@2x.png
macrotasks: script(整体代码), setTimeout,seInterval, setImmediate, I/O,UI rendering
microtasks: process.nextTick, Promises, Object.observe, MutationObserver
任务队列分为macrotasks和microtasks,而Promise中的then方法的函数会被推入microtasks队列,而setTimeout的任务会被推入macrotasks队列。
在每次事件循环中,macrotasks只会提取一个执行,而microtasks会一直提取,直到microtasks队列清空。
那么也就是说如果我的某个microtask任务又推入的一个任务进入microtasks队列,那么在主线程完成该任务之后,仍然会继续运行microtasks任务直到任务队列耗尽。
而事件循环每次只会入栈一个macrotask,主线程执行完该任务后又会先检查microtasks队列并完成里面的所有任务后再执行macrotask。
需要强调的是浏览器为了能够使得js内部的macrotask与DOM任务能够有序的执行,会在一个task执行结束后,在下一个task开始执行前,对页面进行重新渲染
(task->渲染->task->...)
所以总结一下运行机制:
执行一个宏任务(栈中没有就从事件队列中获取)
执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

WX20200111-165142@2x.png