1、首先JS是单线程语言,包括同步任务、异步任务,异步任务又包括宏观任务和微观任务
2、宏观任务的方法有:script(整体代码)、setTimeout、setInterval、I/O、UI交互事件、postMessage、MessageChannel、setImmediate(Node.js 环境)
3、微观任务的方法有:Promise.then(promise后面的.then才是微观任务)、MutaionObserver、process.nextTick(Node.js 环境),async里的await
当执行一段js代码时,判断是同步任务还是异步任务。(同步任务放入主线程执行,异步任务放入事件队列执行)整体script是一个宏步任务,先会被读取进入主线程执行,在主线程中所有同步任务按出现顺序执行,途中遇见异步任务就会把异步任务放入任务队列里(微观任务放入微观任务队列表,宏放宏),一旦"主线程"中的所有同步任务执行完毕,系统就会读取"任务队列"(执行任务队列里对应的回调函数)。
"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。先读取微观任务队列,再读取宏观队列,(如果任务队列里的任务还继续含有微宏,继续放在宏微事件队列后面依次排列)。但是,由于"定时器"功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。
Event Loop:主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。
5、实例:
async function async1() {
console.log('2');
await async2();
console.log('await1');
}
async function async2() {
console.log('3');
}
console.log('1');
setTimeout(function() {
console.log('7');
}, 0)
async1();
new Promise(function(resolve) {
console.log('4');
resolve();
}).then(function() {
console.log('6');
});
console.log('5');
(1)从上到下,先走同步任务队列,再走异步任务队列
(2)同步任务:1 → 2 → 3→ 4→ 5
(3)微观任务: await1 → 6
(4)宏观任务:7
记住,await之后的代码必须等await语句执行完成后(包括微任务完成),才能执行后面的,也就是说,只有运行完await语句,才把await语句后面的全部代码加入到微任务行列,必须等await async2函数执行完毕才能对await语句后面的全部代码加入到微任务中。
await 语句是同步的,await语句后面全部代码才是异步的微任务