# 33、任务队列

# JS的定义

JS是一种单线程的语言,这样就意味着同一时间只能完成一件事。在代码中,JS引擎只能在单一线程中处理一次语句。

# 异步运行机制

callback、setTimeOut、ajax等都是通过 事件循环(envent loop)来实现的;

# 什么是Event Loop

主线程运行的时候,产生堆和栈,栈中的代码调用各种API,分发宏任务到任务队列当中,event Loop会一直运行,来执行进入队列的宏任务。一个event Loop 有多种的宏任务来源。但是浏览器每次都会选择一个源中的一个宏任务去执行。

# 宏任务(task)

宏任务

浏览器为了能够使JS内部taskDOM任务之间有序的进行,会在一个task执行结束之后,在下一个task执行开始之前,对页面进行重新渲染(task->渲染->task->渲染->....)

如:鼠标点击会触发一个时间回调,需要执行一个宏任务,然后解析HTML。 还有setTimeout,setTimeout的作用是等待给定的时间后为它的回调产生一个新的宏任务js-33-1

# 微任务(Microtasks)

微任务

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

如:mutation observe 的回调 还有promise的回调 js-33-2

# 完整的事件循环

js-33-3

# 总结

总结

宏任务按照顺序执行,且浏览器在每个宏任务之间渲染页面 所有微任务也按照顺序执行,且在以下场景会立即执行所有微任务

  • 每个回调之后且JS执行栈中为空
  • 每个宏任务结束后

注意: 同步任务执行完成后会先检查微任务队列中是否有任务执行,有的话就挨个执行,没有的话就开始检查宏任务队列中是否有任务,开始执行。

# 事件循环在node中和浏览器中的区别

区别

Node中分好多个阶段,每个阶段都相当于一个宏任务,依次执行。

  • timers 阶段:这个阶段执行 timer(setTimeout、setInterval)的回调
  • I/O callbacks 阶段:处理一些上一轮循环中的少数未执行的 I/O回调
  • idle, prepare 阶段:仅 node 内部使用
  • poll 阶段:获取新的 I/O 事件, 适当的条件下 node 将阻塞在这里
  • check 阶段:执行 setImmediate() 的回调
  • close callbacks 阶段:执行 socketclose 事件回调

上面六个阶段都不包括 process.nextTick()

node10以前:执行一个阶段的所有任务,再执行nextTick队列里的任务,再执行这个阶段中产生的微任务。 node11之后:和浏览器做了统一

上次更新: 5/20/2023, 3:20:58 PM