微任务和宏任务的区别
答案:
微任务和宏任务是异步任务的两个分类。
宏任务:当前调用栈中执行的代码成为宏任务。(主代码块,定时器等)。
微任务:当前(此次事件循环中)宏任务执行完,在下一个宏任务开始之前需要执行的任务,可以理解为回调事件。(Promise.then,proness.nextTick 等等)。
宏任务中的事件放在 callback queue 中,由事件触发线程维护;微任务的事件放在微任务队列中,由 js 引擎线程维护。
在挂起任务时,JS 引擎会将所有任务按照类别分到这两个队伍中,首先在宏任务的队列中取出第一个任务,执行完毕后,取出微任务队列中的所有任务顺序执行;之后再取出宏任务,周而复始,直到两个队列的任务都取完。
其实并不止一个消息队列,有异步队列
和事件队列
,而事件队列总是优先于异步队列被空闲下来的JS线程取用
宏任务一般是:包括整体代码script
,setTimeout
,setInterval
、I/O
、UI render
。
微任务主要是:Promise
、Object.observe
、MutationObserver
。
第一步,先按同步代码顺序运行
第二步,开始清空微任务队列
第三步,开始清空宏任务队列(执行一个宏任务,把相关微任务添加入微任务队列)
第四步:开始清空微任务队列(上一个执行宏任务中加入队列的微任务一次性全部执行完成)
第五步:开始清空宏任务队列(执行下一个宏任务,把相关微任务添加入微任务队列)
..........循环一直到执行完成
来个栗子:
console.log('sync statement 1');
Promise.resolve().then(function() {
console.log('micro task 1');
setTimeout(function() {
console.log('macro task 1');
}, 0);
}).then(function() {
console.log('micro task 2');
});
setTimeout(function() {
console.log('macro task 2')
Promise.resolve().then(function(){
console.log('micro task 3');
})
}, 0)
console.log('sync statement 2');
输出:
//输出:
sync statement 1
sync statement 2
micro task 1
micro task 2
macro task 2
micro task 3
macro task 1
解析 :
console.log('sync statement 1'); // 同步代码,语句1
Promise.resolve().then(function() { // 同步代码,语句2,注册了一个微任务
console.log('micro task 1'); // 微任务,语句3
setTimeout(function() { // 微任务,语句4,同时注册了一个宏任务
console.log('macro task 1'); // 宏任务,语句5
}, 0);
}).then(function() {
console.log('micro task 2'); // 微任务,语句6
});
setTimeout(function() { // 同步代码,语句7
console.log('macro task 2') // 宏任务,语句8
Promise.resolve().then(function(){ // 宏任务,语句9,同时注册了一个微任务
console.log('micro task 3'); // 微任务,语句10
})
}, 0)
console.log('sync statement 2'); // 同步代码,语句11
再来一个栗子:
console.log('1');//
setTimeout(function () {
console.log('2');//
new Promise(function (resolve) {
console.log('3');//
resolve();
}).then(function () {
console.log('4');//
})
}, 0);
new Promise(function (resolve) {
console.log('5');//
resolve();
}).then(function () {
console.log('6');//
});
setTimeout(function () {
console.log('7');//
new Promise(function (resolve) {
console.log('8');//
resolve();
}).then(function () {
console.log('9');//
});
})
答案:
1
5
6
2
3
4
7
8
9