上篇文章说了一下js中定时器 setTimeout 和 setInterval 的执行原理。这两个计时器都是异步执行的,这部分体现了js的执行过程。
js自身执行的模型是事件循环(event loop)。
js在启动时会创建一个循环,每次循环都会去任务队列(task query)里找要进行的任务。当队列里的一个任务执行完毕,该循环会去找下一个任务去执行。js的执行过程就是循环不断地执行。像定时器,用户触发的事件,promise 等异步执行的代码,都会按规定往这个任务队列推。
任务队列不是只有一个,有 microtasks 和 macrotasks 之分。macrotask query 就是 task query,每个 macrotask 里都有一个 microtask。js开始执行时,会先取一个 macrotask,然后取里面的 microtask 去执行。当前的 microtask 执行完毕之后,会取下一个 microtask 直到 microtask 执行完,然后退出改 macrotask,去执行下一个 macrotask,然后就一直循环下去。就相当于有一个 task query,而这个队列中的每一个 task,也相当于一个 task query。
因此我们观察到的现象直观地来说,就是这些异步方法有一个优先级,microtask 要比 macrotask 优先级高,优先级高的会比优先级低的先执行,同优先级的就根据进入队列的时间去执行。
macrotasks: setTimeout setInterval setImmediate I/O UI渲染
microtasks: Promise process.nextTick Object.observe MutationObserver
看一个例子:
1 console.log(‘start‘) 2 ?3 Promise.resolve().then(() => { 4 ????console.log(‘promise 1‘) 5 }) 6 ?7 setTimeout(() => { 8 ????console.log(‘setTimeout 1‘) 9 ????Promise.resolve().then(() => {10 ????????console.log(‘promise 2‘)11 ????????Promise.resolve().then(() => {12 ????????????console.log(‘promise 3‘)13 ????????}).then(() => {14 ????????????console.log(‘promise 4‘)15 ????????})16 ????}).then(() => {17 ????????setTimeout(() => {18 ????????????console.log(‘setTimeout 2‘)19 ????????????Promise.resolve().then(() => {20 ????????????????console.log(‘promise 5‘)21 ????????????})22 ????????}, 0)23 ????????console.log(‘promise 6‘)24 ????})25 ????console.log(‘setTimeout 2‘)26 }, 0)27 28 setTimeout(() => {29 ????console.log(‘setTimeout 3‘)30 ????Promise.resolve().then(() => {31 ????????console.log(‘promise 7‘)32 ????})33 ????console.log(‘setTimeout 4‘)34 }, 0)35 36 Promise.resolve().then(() => {37 ????console.log(‘promise 8‘)38 })
执行结果为
js事件循环 microtask macrotask
原文地址:http://www.cnblogs.com/ClassicL/p/7978564.html