异步
异步任务介绍
1.宏任务
也称为任务队列,宏任务现在分为用户交互任务队列,延时任务队列,网络请求任务队列等,不仅仅局限于一个队列中;script(整体代码)、setTimeout、setInterval、UI交互事件、postMessage、Ajax,I/0,UI交互,postMessage,setImmediate(Node.js 环境)。
2.微任务
也称为Job队列,Promise队列;Promise.then catch finally、queueMicrotask、MutaionObserver、Object.observe、Promise.resolve、Promise.reject、process.nextTick(Node.js 环境)。
同步任务的主线程队列会比异步任务的宏任务和微任务先运行。
异步任务的执行顺序为:
分析以下代码,判断其执行顺序:
<!-- 点击事件宏任务 -->
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<button>点击</button>
</body>
<script>
// 宏任务 - 用户交互事件
document.querySelector('button').addEventListener('click', function () {
console.log('宏任务 - 用户交互事件');
});
setTimeout(()=>{
console.log('宏任务-setTimeout')
},2000)
// 微任务 - Promise 的 then 方法
new Promise(function (resolve, reject) {
console.log('微任务 - Promise');
resolve();
console.log('主线程任务')
}).then(function () {
console.log('微任务 - Promise 的 then 方法');
});
console.log('主线程执行');
</script>
</html>
执行顺序:
微任务 - Promise
主线程任务
主线程执行
微任务 - Promise 的 then 方法
宏任务-setTimeout
宏任务 - 用户交互事件 (点击触发)
vue3 nextTick 示例代码
无注释版
import {nextTick} from 'vue'
setTimeout(() => {
console.log(2)
new Promise(() => {
console.log(9)
})
setTimeout(() => {
console.log(3)
})
})
nextTick(() => {
console.log(4)
setTimeout(() => {
console.log(5)
})
})
let promise = new Promise((resolve, reject) => {
setTimeout(() => {
console.log(6)
})
resolve()
console.log(7)
}).then(() => {
console.log(8)
})
console.log(1)
有注释版:
import {nextTick} from 'vue'
setTimeout(() => {
// 5. 此时微任务队列被清空,开始宏任务,执行宏任务,第一层
console.log(2)
// 6. 宏任务中的同步代码,执行
new Promise(() => {
console.log(9)
})
// 9. 宏任务的宏任务,第二层
setTimeout(() => {
console.log(3)
})
})
// nextTick实际上也是执行一个微任务
nextTick(() => {
// 3. 开始执行微任务
console.log(4)
// 8. 微任务中的宏任务,先进去延时队列,第二层
setTimeout(() => {
console.log(5)
})
})
// 特殊说明: new Promise()属于同步任务
let promise = new Promise((resolve, reject) => {
// 7. 按照调用顺序,执行以下宏任务,第一层
setTimeout(() => {
console.log(6)
})
// 2. 调用resolve(),将.then()回调添加至微任务队列,会在当前执行栈的最后才执行
resolve()
// 1. 同步任务,所以先输出
console.log(7)
}).then(() => {
// 4. 执行Promise.then()
console.log(8)
})
console.log(1)
// 7 1 4 8 2 9 6 5 3