同步任务和异步任务
同步任务 即可以立即执行的任务,例如 console.log() 打印一条日志、声明一个变量或者执行一次加法操作等。
异步任务 相反不会立即执行的事件任务。异步任务包括宏任务和微任务。
常见的异步操作:
Ajax
DOM的事件操作
setTimeout
Promise的then方法
Node的读取文件
宏任务(macrotask)
script(全局任务), setTimeout, setInterval, setImmediate, I/O, UI rendering
微任务(macrotask)
process.nextTick, Promise.then(), Object.observe, MutationObserver
在微任务中 process.nextTick 优先级高于Promise
当一个异步任务入栈时,主线程判断该任务为异步任务,并把该任务交给异步处理模块处理,当异步处理模块处理完打到触发条件时,根据任务的类型,将回调函数压入任务队列。
如果是宏任务,则新增一个宏任务队列,任务队列中的宏任务可以有多个来源。
如果是微任务,则直接压入微任务队列
执行机制:
1、从全局任务 script开始,任务依次进入栈中,被主线程执行,执行完后出栈。
2、遇到异步任务,交给异步处理模块处理,对应的异步处理线程处理异步任务需要的操作,例如定时器的计数和异步请求监听状态的变更。
3、当异步任务达到可执行状态时,事件触发线程将回调函数加入任务队列,等待栈为空时,依次进入栈中执行。
到这问题就来了,当异步任务进入栈执行时,是宏任务还是微任务呢?
1、由于执行代码入口都是全局任务 script,而全局任务属于宏任务,所以当栈为空,同步任务任务执行完毕时,会先执行微任务队列里的任务。
2、微任务队列里的任务全部执行完毕后,会读取宏任务队列中拍最前的任务。
3、执行宏任务的过程中,遇到微任务,依次加入微任务队列。
4、栈空后,再次读取微任务队列里的任务,依次类推。
总之:先是同步任务,完了微任务,再是宏任务,当宏任务包含微任务,先执行微任务,再继续宏任务
看下面的实例:
setTimeout(function () {
console.log(1);
Promise.resolve().then(function () {
console.log(2);
});
}, 0);
setTimeout(function () {
console.log(3);
}, 0);
Promise.resolve().then(function () {
console.log(4);
});
console.log(5);
第一轮循环
1、同样从全局任务入口,遇到宏任务 setTimeout,交给异步处理模块,我们暂且先记为 setTimeout1,由于等待时间为 0,直接加入宏任务队列。
2、再次遇到宏任务 setTimeout,交给异步处理模块,我们暂且先记为 setTimeout2,同样直接加入宏任务队列。
遇到微任务 then(),加入微任务队列。
3、最后遇到打印语句,直接打印日志 5。

第二轮循环
1、栈空后,先执行微任务队列中的 then()方法,输出 4,此时微任务队列为空。

第三轮循环
1、先执行微任务队列中的 then()方法,输出 2,此时微任务队列为空。

2、继续读取宏任务队列的最靠前的任务 setTimeout2。
3、直接执行打印语句,打印日志 3。第三轮循环结束,执行完毕。

最后我们是我们的boss,欢迎大家在评论区留言写出自己心中的那个正确答案。
console.log('1');
setTimeout(function() {
console.log('2');
new Promise(function(resolve) {
console.log('3');
resolve();
}).then(function() {
console.log('4')
})
})
new Promise(function(resolve) {
console.log('5');
resolve();
}).then(function() {
console.log('6')
})
setTimeout(function() {
console.log('7');
})
setTimeout(function() {
console.log('8');
new Promise(function(resolve) {
console.log('9');
resolve();
}).then(function() {
console.log('10')
})
})
new Promise(function(resolve) {
console.log('11');
resolve();
}).then(function() {
console.log('12')
})
console.log('13');

网友评论