宏任务、微任务、同步任务、异步任务的执行顺序
关于这四个的执行顺序,今天梳理了一遍,用白话记录一下
先区分同步任务和异步任务:
同步任务:立即执行的任务,直接被JS主线程读取并执行
异步任务:异步执行的任务,会交给任务队列,在宿主环境中执行(宿主环境一般包括:浏览器、node环境)
为什么分为同步任务和异步任务?因为JS是单线程的,如果不区分同步和异步任务,那遇到耗时任务的时候,进程就会卡在当前无法往下走,所以又将非耗时任务归为同步任务,耗时任务归位异步任务。其中异步任务又分为微任务和宏任务。
● 常见的微任务包括: promise 的回调
● 常见的宏任务包括: script 脚本的执行、setTimeout ,setInterval 可以理解为耗时长的任务
关于四个的执行顺序见如下代码
setTimeout(() => {
console.log(1);
new Promise((resolve, rej) => {
console.log(6);
resolve(7);
})
.then((res) => {
console.log(res);
return new Promise((resolve, rej) => {
resolve(9999);
});
})
.then((res) => {
console.log(res);
});
console.log(8);
}, 200);
setTimeout(() => {
console.log(9);
new Promise((resolve, rej) => {
console.log(10);
resolve(11);
}).then((res) => {
console.log(res);
});
console.log(12);
}, 300);
console.log(2);
new Promise((resolve, reject) => {
console.log(3);
resolve(4);
})
.then((res) => {
console.log(res);
return new Promise((resolve, rej) => {
resolve(5);
});
})
.then((res) => {
console.log(res);
});
一、看所有同步任务,两个setTimeout显然不会立即执行,肉眼可见的是(2),new Promise的过程是同步的,但.then里面的代码上述说了promise回调是异步的,所以 (2、3)
二、同步任务执行完后,执行异步代码,异步中(一个promise回调,两个setTimeout)先执行微任务 (promise),promise回调中执行顺序(4、5),所以输出(2,3,4,5)
三、所有微任务队列执行完后,执行一个宏任务(第一个setTimeout时间短,先执行),执行过程中,发现promise,放到微任务队列,此时输出(1,6,8),然后执行下一个宏任务,setTimeout。!!注意 执行下一个宏任务之前,会检查微任务队列有没有任务,如果有,执行所有队列中的微任务。此时输出(7、9999),所以控制台目前(2,3,4,5,1,6,8,7,9999)。执行完所有任务队列中的微任务后,执行下一个宏任务(setTimeout)结果同理(9,10,12)后,放promise到微任务队列,然后输出(11)
最终结果(2,3,4,5,1,6,8,7,9999,9,10,12,11)