引言
我们知道JavaScript是单线程执行代码的,当js引擎从上往下执行代码时,会区分哪些代码是同步任务代码,哪些代码是异步任务。异步任务包括宏任务和微任务,js引擎会先执行完同步任务代码,再去执行异步任务代码。
宏任务
常见的宏任务:I/O,setTimeout,setInterval,setImmediate,Ajax等事件
微任务
常见的微任务:process.nextTick,MutationObserver,Promise.then/catch/finally
事件循环
当js引擎从上往下执行时,碰到宏任务,会将宏任务放进宏任务队列中等待;碰到微任务,会将微任务放进微任务队列中等待,直到将所有的同步任务执行结束,开始事件循环进行微任务和宏任务的执行。每个宏任务之后,引擎会立即执行微任务队列中的所有任务,然后再执行其他的宏任务,或者渲染。 例如:看下面示例:
setTimeout(()=> alert('张三'))
Promise.resolve().then(()=> alert('王五'))
alert('李四')
思考这里的执行顺序,在js引擎执行第一行代码,会把setTimeout的回调放进宏任务队列等待,执行第二行代码时,z执行.then方法后,会将.then的回调放入微任务队列,执行到第三行同步代码后,再开始去执行微任务队列里的所有任务,微任务执行完,去执行宏任务队列中的第一个任务。这个任务执行完再继续查看微任务队列是否有任务需要执行,以此循环。
所以执行顺序是:‘李四’,‘王五’,‘张三’
总结事件循环
- 从宏任务队列出队,并执行该宏任务
- 轮询微任务队列,队列非空时,执行所有的微任务
- 如果有变更,进行渲染
- 轮询宏任务队列,宏任务为空时,则等待新的任务;不为空时,转到步骤1
检验时刻
练习一下,看看理解到位了没,答案就在在下方。
console.log(1)
setTimeout(() => console.log(2), 3000)
Promise.resolve().then(() => console.log(3))
Promise.resolve().then(() => setTimeout(() => console.log(4), 2000))
Promise.resolve().then(() => console.log(5))
setTimeout(() => console.log(6), 1000)
console.log(7)
输出结果为:1 7 3 5 6 4 2
你做对了吗?