同步任务、异步任务、宏任务、微任务
js任务分为同步任务和异步任务;异步任务又分为宏任务和微任务
- 同步任务:在主线程上按顺序执行,Promise属于同步任务。
- 异步任务:异步任务不会立即执行,它们依赖事件循环进行调度。异步任务包含宏任务和微任务,它们在特定时间点被推入各自的任务队列中等待执行。
- 宏任务 :常见的宏任务包括:script整体代码 、setTimeout 、setInterval 、I/O操作 、UI交互事件 、postMessage 、MessageChannel 、setImmediate等
- 微任务 :常见的微任务包括:Promise的回调(.then 、.catch 、.finally )、MutationObserver的回调 、process.nextTick
js执行顺序
同步任务------》微任务------》宏任务------》微任务------》宏任务------》...
一次事件循环
- 执行当前宏任务:事件循环首先从宏任务队列中取出第一个任务执行。
- 执行所有微任务:当前宏任务执行完毕后,事件循环会检查微任务队列,事件循环会一次执行队列中所有微任务,知道微任务队列清空。
- 渲染UI(如果需要):在浏览器环境中,一旦微任务队列清空,浏览器会检查是否需要执行UI渲染。通常,浏览器的UI渲染会在执行完所有微任务之后,下一个宏任务开始之前进行。
- 继续下一个宏任务:完成当前宏任务、所有微任务以及可能的UI渲染之后,事件循环会回到第一步,从宏任务队列中取出下一个任务,开始新一轮的执行。
实践
js
;(() => {
console.log(1)
setTimeout(() => {
console.log('setTimeout 1')
Promise.resolve().then(() => {
console.log('promise 1')
})
})
setTimeout(() => {
console.log('setTimeout 2')
Promise.resolve().then(() => {
console.log('promise 2')
})
})
Promise.resolve().then(() => {
console.log('promise 3')
Promise.resolve().then(() => {
console.log('promise 4')
})
})
Promise.resolve().then(() => {
console.log('promise 5')
Promise.resolve().then(() => {
console.log('promise 6')
})
})
console.log(7)
})()
执行步骤解析
javascript整体代码
注册了一个宏任务,放入宏任务队列。- 此时执行栈/主线程空闲,事件循环从宏任务队列中取出一个宏任务执行。
console.log(1)
为同步任务,会立即执行,输出1
。setTimeout(() => { console.log('setTimeout 1') Promise.resolve().then(() => { console.log('promise 1') }) })
注册一个宏任务,放入宏任务队列。setTimeout(() => { console.log('setTimeout 2') Promise.resolve().then(() => { console.log('promise 2') }) })
注册一个宏任务,放入宏任务队列。Promise.resolve().then(() => { console.log('promise 3') Promise.resolve().then(() => { console.log('promise 4') }) })
注册一个微任务,放入微任务队列。Promise.resolve().then(() => { console.log('promise 5') Promise.resolve().then(() => { console.log('promise 6') }) })
注册一个微任务,放入微任务队列。console.log(7)
为同步任务,立即执行,输出7
。- 主线程空闲,检查微任务队列,取出一个微任务
Promise.resolve().then(() => { console.log('promise 3') Promise.resolve().then(() => { console.log('promise 4') }) })
执行then回调,输出promise 3
。 Promise.resolve().then(() => { console.log('promise 4') })
注册一个微任务,放入微任务队列队尾。- 取出下一个微任务
Promise.resolve().then(() => { console.log('promise 5') Promise.resolve().then(() => { console.log('promise 6') }) })
执行then回调,输出promise 5
。 Promise.resolve().then(() => { console.log('promise 6') })
注册一个微任务,放入微任务队列队尾。- 取出下一个微任务
Promise.resolve().then(() => { console.log('promise 4') })
执行then回调,输出promise 4
。 - 取出下一个微任务
Promise.resolve().then(() => { console.log('promise 6') })
执行then回调,输出promise 6
。 - 此时微任务队列清空,无UI渲染需求,开启下一轮事件循环,执行下一个宏任务。取出一个宏任务
setTimeout(() => { console.log('setTimeout 1') Promise.resolve().then(() => { console.log('promise 1') }) })
输出setTimeout 1
。 Promise.resolve().then(() => { console.log('promise 1') })
注册一个微任务,放入微任务队列。- 检查微任务队列,取出一个微任务
Promise.resolve().then(() => { console.log('promise 1') })
执行then回调,输出promise 1
。 - 此时微任务队列清空,无UI渲染需求,开启下一轮事件循环,执行下一个宏任务。取出一个宏任务
setTimeout(() => { console.log('setTimeout 2') Promise.resolve().then(() => { console.log('promise 2') }) })
输出setTimeout 2
。 Promise.resolve().then(() => { console.log('promise 2') })
注册一个微任务,放入微任务队列。- 检查微任务队列,取出一个微任务
Promise.resolve().then(() => { console.log('promise 2') })
执行then回调,输出promise 2
。 - 此时微任务队列清空,宏任务队列也清空,所有任务执行完毕。
输出结果为
arduino
1
7
promise 3
promise 5
promise 4
promise 6
setTimeout 1
promise 1
setTimeout 2
promise 2