首先,js是单线程语言,他会从上到下依次执行代码,在执行过程中可能会有同步任务和异步任务。
同步任务:直接放入主线程执行。比如for循环,循环结束后在执行下面的代码
异步任务:可能需要等待一定时间才有返回或者执行。比如ajax请求,比如setTimeout(func(), 1000),js不可能一直等待,否则效率会变得很低,所以这些任务会被放入Event table,当他们满足特定的条件(比如,ajax请求结果返回),再被放入Event queue
主线程执行完同步任务后,主线程空闲后执行任务队列中的任务
任务队列中的任务又分为两种,宏任务和微任务
| 任务(代码) | 宏/微任务 | 环境 |
|---|---|---|
| 事件 | 宏任务 | 浏览器 |
| 网络请求ajax | 宏任务 | 浏览器 |
| setTimeout | 宏任务 | 浏览器/node |
| setImmediate | 宏任务 | node |
| Promise.then().catch().finally() | 微任务 | 浏览器/node |
| process.nextTick | 微任务 | node |
js线由上到下执行,执行过程中如果产出新的宏/微任务,就将他们推入相应的任务队列,之后在执行一队微任务,之后再执行宏任务,如此循环。以上不断重复的过程就叫做 Event Loop(事件循环)。
如果不理解可尝试一下代码
console.log('script start')
new Promise((resolve, reject) => {
console.log('promise1')
setTimeout(() => {
console.log('setTimeout1')
})
resolve()
})
.then((res) => {
console.log(promise2)
new Promise((resolve, reject) => {
console.log('promise3')
setTimeout(() => {
console.log('setTimeout2')
})
resolve()
}).then((res) => {
console.log(promise4)
setTimeout(() => {
console.log('setTimeout3')
})
})
setTimeout(() => {
console.log('setTimeout4')
})
})
.then((res) => {
console.log('promise5')
setTimeout(() => {
console.log('setTimeout5')
})
})
setTimeout(() => {
console.log('setTimeout6')
new Promise((resolve, reject) => {
console.log('promise6')
setTimeout(() => {
console.log('setTimeout7')
})
resolve()
}).then((res) => {
console.log(promise7)
setTimeout(() => {
console.log('setTimeout8')
})
})
})
console.log('script end')
注意【】中的是放入队列的,不会直接输出
进入事件循环,
console.log('script start')
执行promise主体
console.log('promise1')
宏任务队列【console.log('setTimeout1')】
微任务队列【console.log(promise2)】加入,这里不会触发第2个.then
宏任务队列【console.log('setTimeout6')】
console.log('script end')
此时第一次循环结束
开始循环微任务队列
console.log(promise2)
执行promise主体
console.log('promise3')
宏任务队列【console.log('setTimeout2')】
微任务队列【console.log(promise4)】
宏任务队列【console.log('setTimeout4')】
微任务队列【console.log(promise5)】
此时微任务队列中又有新任务
console.log(promise4)
宏任务队列【console.log('setTimeout3')】
console.log(promise5)
宏任务队列【console.log('setTimeout5')】
微任务队列空了,执行宏任务队列
console.log('setTimeout1')
console.log('setTimeout6')
console.log(promise6)
微任务队列【console.log(promise7)】
宏任务队列【console.log('setTimeout7')】
发现微任务队列中有新的任务,执行微任务队列
console.log(promise7)
宏任务队列【console.log('setTimeout8')】
微任务队列空了,执行宏任务队列
console.log('setTimeout2')
console.log('setTimeout4')
console.log('setTimeout3')
console.log('setTimeout5')
console.log('setTimeout7')
console.log('setTimeout8')
以下为打印结果