浏览器的Event Loop
进入整体代码【宏任务】后,开始第一次循环,接着执行(所有)微任务;然后再从宏任务队列开始,执行队列中(第一个)宏任务,接着(清空)微任务队列;然后再从宏任务队列开始......
- 同步代码 —> 所有微任务 —> 第一个宏任务 —> 所有微任务 —> ......
for (var i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i) // 3、10个 10
}, 0)
console.log(i) // 1、0 ~ 9
}
console.log(i) // 2、1个 10
for (let i = 0; i < 10; i++) {
setTimeout(() => {
console.log(i) // 3、0 ~ 9
}, 0)
console.log(i) // 1、0 ~ 9
}
console.log(i) // 2、Uncaught ReferenceError: i is not defined
Node的Event Loop
每个【阶段】所有任务完成后,清空微任务队列,每一轮事件循环,分六个依次执行的阶段,每阶段都有一个回调函数队列。只有该队列清空了,事件循环才会进入下一个阶段
- 同步代码 —> 所有微任务 —> 下一个阶段 —> 所有微任务 —> ......
setTimeout(() => {
console.log('1')
process.nextTick(() => console.log('2'))
}, 1000)
process.nextTick(() => {
setTimeout(() => console.log('3'), 1000)
console.log('4')
})
// 1、概率大:4-1-3-2 或 2、概率小:4-1-2-3
console.log('1')
setTimeout(() => {
console.log('2')
process.nextTick(() => console.log('3'))
setImmediate(() => console.log('4'))
}, 0)
process.nextTick(() => console.log('5'))
setImmediate(() => {
console.log('6')
process.nextTick(() => console.log('7'))
})
// 1、概率大:1-5-2-3-6-4-7 或 2、概率小:1-5-6-7-2-3-4
- 如果有多个process.nextTick语句(不管它们是否嵌套),将全部在【当前执行栈之后,读取任务队列之前】执行
process.nextTick(function A () {
console.log(1)
process.nextTick(function B () {
console.log(2)
process.nextTick(function C () {
console.log(3)
setTimeout(function timeout () {
console.log('setTimeout1')
}, 0)
})
})
})
setTimeout(function timeout () {
console.log('setTimeout2')
}, 0)
console.log('start')
// start
// 1
// 2
// 3
// setTimeout2
// setTimeout1