先执行同步任务,再执行异步任务。对于所有任务,还可以分为宏任务和微任务
了解宏任务和微任务
宏任务
一些任务的回调会作为宏任务依次进入宏队列(macro tack),等待后续被调用。
这些任务包括:
- script全部代码
- setTimeout
- setInterval
- setImmediate
- requestAnimationFrame(浏览器独有)
- I/O
- UI rendering(浏览器独有)
微任务
另一些任务的回调会作为微任务依次进入微队列(micro tack),等待后续被调用。
- process.nextTick
- Promise
- Object.observe
- MutationObserver
job queue中的执行顺序:
假设有如下工作任务:
macro tack队列: a1, a2, a3
micro tack队列:b1, b2, b3
- 首先执行macro tack队列的第一个任务:a1
- 继而按顺序执行micro tack队列中的全部任务,即 b1, b2, b3,执行完毕后即清空了micro tack队列中的所有任务
- 接着执行macro tack队列中剩下的任务:a2, a3
由此可得到的执行顺序为:
script(主程序代码)–> process.nextTick --> Promise … --> setTimeout --> setInterval --> setImmediate --> I/O --> UI rendering
- 在执行微任务时,如果又产生了micro tack,则会继续添加到队列的末尾,也会在这个周期执行,直到micro task queue为空为止。
例子:
console.log('script1');
setTimeout(function(){
console.log('setTimeout2')
}, 1000)
setTimeout(function(){
console.log('setTimeout3')
}, 200)
console.log('script4')
输出顺序:
先按顺序执行主程序代码,再执行队列中的任务:setTimeout3 在200ms时添加到了任务队列,setTimeout3 在1000ms时添加到任务队列,故先输出setTimeout3。
再看一个例子:
console.log('script1');
setTimeout(function(){
console.log('setTimeout2')
}, 1000)
setTimeout(function(){
console.log('setTimeout3')
}, 200)
Promise.resolve().then(function() {
console.log('promise1')
}).then(function() {
console.log('promise2')
})
console.log('script4')
输出顺序:
按照惯例先执行主程序代码,此时有微任务promise,故先按顺序执行微任务,再执行宏任务。