异步是一个初期不怎么能遇到但是又十分重要的知识点。
而且复杂。
掉了三节更新的课程还没有看,罪过啊
众所周知,javascript是单线程,但是单线程的弊端也很明显,就是很多时间都浪费在等待某一个事件执行加载上面了。为了提高效率,我们在js中也实现了异步。
- 回调函数
- promise
- generator
- async/awiat
setTimeout的内容会被放入到执行队列中,不会马上执行,等到主线程执行栈中的任务执行完了之后才会执行setTimeout中的内容
宏任务和微任务:
宏任务一般包括: setTimeout setInterval I/O 事件 postMessage setImmediate (Node.js) requestAnimationFrame UI渲染
微任务一般包括: Promise.then MutationObserver process.nextTick(Node.js)
由上分析得知,每次主线程执行栈为空的时候,引擎会优先处理微任务队列,处理完微任务队列里的所有任务,再去处理宏任务。
即 promise在setTimeout之前执行
async function async1() {
console.log('async1 start') // step 4: 直接打印同步代码 async1 start
await async2() // step 5: 遇见 await,首先执行其右侧逻辑,并在这里中断 async1 函数
console.log('async1 end') // step 11: 再次回到 async1 函数,await 中断过后,打印代码 async1 end
}
async function async2() {
console.log('async2') // step 6: 直接打印同步代码 async2,并返回一个 resolve 值为 `undefined` 的 promise
}
console.log('script start') // step 1: 直接打印同步代码 script start
// step 2: 将 setTimeout 回调放到宏任务中,此时 macroTasks: [setTimeout]
setTimeout(function() {
console.log('setTimeout') step 13: 开始执行宏任务,输出 setTimeout
}, 0)
async1() // step 3: 执行 async1
// step 7: async1 函数已经中断,继续执行到这里
new Promise(function(resolve) {
console.log('promise1') // step 8: 直接打印同步代码 promise1
resolve()
}).then(function() { // step 9: 将 then 逻辑放到微任务当中
console.log('promise2') // step 12: 开始执行微任务,输出 promise2
})
console.log('script end') // step 10: 直接打印同步代码 script end,并回到 async1 函数中继续执行