宏任务(macro-task)、微任务(micro-task)
JavaScript 单线程中的任务可以细分为宏任务和微任务。
宏任务包括:
- script(整体代码)
- setTimeout
- setInterval
- setImmediate
- I/O
- UI rendering
微任务包括:
- process.nextTick
- Promises
- Object.observe
- MutationObserver
js执行过程
- 整段代码作为宏任务进入主线程执行。
- 遇到了异步任务,一种进行事件注册,等指定的时间后将回调函数放入任务队列中,或者直接将任务放在任务队列。
- 第一次循环完成之后,检测微任务的任务队列中是否存在任务,存在就执行。
- 接着再到宏任务的任务队列中按顺序取出一个宏任务到执行栈执行。
- 执行栈任务执行完成检测是否有微任务,有微任务则微任务进执行栈,没有微任务开始进行下一次事件循环,执行队列中的宏任务。
- 当检测到任务队列中已经没有了要执行的任务,那么就结束事件循环。
例:
console.log(1)
setTimeout(()=>{
console.log(2)
},1000)
setTimeout(()=>{
console.log(3)
new Promise((res,rej)=>{
console.log(4)
res()
}).then(()=>{
console.log(5)
})
},1000)
new Promise((res,rej)=>{
console.log(6)
res()
}).then(()=>{
console.log(7)
})
setTimeout(()=>{
console.log(8)
},0)
setTimeout(()=>{
console.log(9)
},1000)
cconsole.log(10)
执行过程
-
执行
console.log(1)
。 -
setTimeout(()=>{ console.log(2) },1000)
进入event table,1s后进入任务队列(宏任务)。 -
setTimeout(()=>{ console.log(3); new Promise((res,rej)=>{ console.log(4); res(); }).then(()=>{ console.log(5); }) },1000)
进入event table,1s后进入任务队列(宏任务)。 -
执行
console.log(6)
,将then
函数放进任务队列(微任务)。 -
setTimeout(()=>{ console.log(8) },0)
进入event table,并很快进入任务队列(宏任务)。 -
setTimeout(()=>{ console.log(9) },1000)
进入event table,1s后进入任务队列(宏任务)。 -
执行
cconsole.log(10)
。 -
第一次循环结束,输出 1 6 10。
-
队列中then 方法出队列,执行
console.log(7)
-
微任务队列清空。
-
setTimeout(()=>{ console.log(8) },0)
出队列,执行console.log(8)
。 -
setTimeout(()=>{ console.log(2) },1000)
出队列,执行console.log(2)
。 -
setTimeout(()=>{ console.log(3); new Promise((res,rej)=>{ console.log(4); res(); }).then(()=>{ console.log(5); }) },1000)
出队列,进入执行栈,输出console.log(3)
, 接着输出console.log(4)
,then方法进入队列(微任务)。 -
队列中有微任务,then方法进入执行栈,输出
console.log(5)
。 -
setTimeout(()=>{ console.log(9) },1000)
出队列,执行console.log(9)
。
结果: 1 6 10 7 8 2 3 4 5 9