参考:https://blog.csdn.net/weixin_45494667/article/details/107296746
一、简介
- 同步任务(MainTask):同步任务是指JavaScript按照正常顺序执行的代码,比如:函数调用,数值运算等等,只要是执行后立即能够得到结果的就是同步任务。
- 宏任务 (MacroTask):setTimeout、setInterval、I/O、UI渲染
- 微任务 (MicroTask) :Promise、Object.obsever、MutationObsever 用户交互事件(User Interaction Event):点击事件onclick、键盘事件onkeywodn、鼠标事件onmouseover等等
二、执行顺序
具体流程:
- 执行完主逻辑中的同步任务
- 取出微任务队列(MicroTask Queue)中的任务执行,直到队列被完全清空 取出宏任务队列(MacroTaskQueue)中的一个任务执行。
- 取出微任务队列(MicroTask Queue)中的任务执行,直到队列被完全清空 重复 3 和 4,直到宏任务队列(MacroTaskQueue)被清空。
宏任务(MacroTask)和微任务(MicroTask)执行顺序
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>demo1:宏任务(MacroTask)和微任务(MicroTask)执行顺序</title>
</head>
<body>
<script type="text/javascript">
console.log('同步任务1 start');
setTimeout(function () {
console.log('宏任务1:setTimeout...');
}, 0);
Promise.resolve().then(function () {
console.log('微任务1 Promise.then() 1')
}).then(function () {
console.log('微任务2 Promise.then() 2')
});
setTimeout(function () {
console.log('宏任务2:setTimeout...');
Promise.resolve().then(function () {
console.log('宏任务2:setTimeout => 微任务 Promise.then()')
});
}, 0);
setTimeout(function () {
console.log('宏任务3:setTimeout...');
}, 0);
Promise.resolve().then(function () {
console.log('微任务3 Promise.then() 1')
}).then(function () {
console.log('微任务3 Promise.then() 2')
})
console.log('同步任务2 end');
</script>
</body>
</html>
三、promise
Promise 的回调函数属于异步任务,会在同步任务之后执行。
new Promise(function (resolve, reject) {
resolve(1);
}).then(console.log);
console.log(2);
// 2
// 1
上面代码会先输出2,再输出1。因为console.log(2)是同步任务,而then的回调函数属于异步任务,一定晚于同步任务执行。
但是,Promise 的回调函数不是正常的异步任务,而是微任务(microtask)。它们的区别在于,正常任务追加到下一轮事件循环,微任务追加到本轮事件循环。这意味着,微任务的执行时间一定早于正常任务。
setTimeout(function() {
console.log(1);
}, 0);
new Promise(function (resolve, reject) {
resolve(2);
}).then(console.log);
console.log(3);
// 3
// 2
// 1
上面代码的输出结果是321。这说明then的回调函数的执行时间,早于setTimeout(fn, 0)。因为then是本轮事件循环执行,setTimeout(fn, 0)在下一轮事件循环开始时执行。