# 33、任务队列
# JS的定义
JS是一种单线程的语言,这样就意味着同一时间只能完成一件事。在代码中,JS引擎只能在单一线程中处理一次语句。
# 异步运行机制
callback、setTimeOut、ajax等都是通过 事件循环(envent loop)来实现的;
# 什么是Event Loop
主线程运行的时候,产生堆和栈,栈中的代码调用各种API,分发宏任务到任务队列当中,
event Loop会一直运行,来执行进入队列的宏任务。一个event Loop有多种的宏任务来源。但是浏览器每次都会选择一个源中的一个宏任务去执行。
# 宏任务(task)
宏任务
浏览器为了能够使JS内部task与DOM任务之间有序的进行,会在一个task执行结束之后,在下一个task执行开始之前,对页面进行重新渲染(task->渲染->task->渲染->....)
如:鼠标点击会触发一个时间回调,需要执行一个宏任务,然后解析HTML。
还有setTimeout,setTimeout的作用是等待给定的时间后为它的回调产生一个新的宏任务。

# 微任务(Microtasks)
微任务
微任务通常来说就是要在当前task执行结束后立即执行的任务,比如对一系列动作做出的反馈,或者是需要异步的执行任务而又不需要分配一个新的task,这样便可以减小一点性能的开销。只要执行栈中没有其他的JS代码正在执行且每个宏任务执行完,微任务队列会立即执行。如果在微任务执行期间微任务队列加入了新的微任务,会将新的微任务加入队列的尾部,之后也会被执行。所有微任务执行的时候,当前执行栈的代码必须已经执行完毕。
如:mutation observe 的回调
还有promise的回调

# 完整的事件循环
# 总结
总结
宏任务按照顺序执行,且浏览器在每个宏任务之间渲染页面 所有微任务也按照顺序执行,且在以下场景会立即执行所有微任务
- 每个回调之后且
JS执行栈中为空 - 每个宏任务结束后
注意: 同步任务执行完成后会先检查微任务队列中是否有任务执行,有的话就挨个执行,没有的话就开始检查宏任务队列中是否有任务,开始执行。
# 事件循环在node中和浏览器中的区别
区别
Node中分好多个阶段,每个阶段都相当于一个宏任务,依次执行。
timers阶段:这个阶段执行timer(setTimeout、setInterval)的回调I/O callbacks阶段:处理一些上一轮循环中的少数未执行的I/O回调idle, prepare阶段:仅node内部使用poll阶段:获取新的I/O事件, 适当的条件下node将阻塞在这里check阶段:执行setImmediate()的回调close callbacks阶段:执行socket的close事件回调
上面六个阶段都不包括 process.nextTick()
node10以前:执行一个阶段的所有任务,再执行nextTick队列里的任务,再执行这个阶段中产生的微任务。
node11之后:和浏览器做了统一
