js事件循环机制和优先级

浏览器的渲染进程是多线程,包括

  • GUI渲染线程
  • js引擎线程
  • 事件触发线程
  • 定时器触发线程
  • 异步http请求线程

主执行栈和任务队列
所有的任务可以分为同步任务和异步任务,同步任务,顾名思义,就是立即执行的任务,同步任务一般会直接进入到主线程中执行;而异步任务,就是异步执行的任务,比如ajax网络请求,setTimeout 定时函数等都属于异步任务,异步任务会通过任务队列( Event Queue )的机制来进行协调
在这里插入图片描述
同步和异步任务分别进入不同的执行环境,同步的进入主线程,即主执行栈,异步的进入 Event Queue 。主线程内的任务执行完毕为空,会去 Event Queue 读取对应的任务,推入主线程执行。 上述过程的不断重复就是我们说的 Event Loop (事件循环)。

宏任务与微任务

从任务层面,在JS引擎中,我们可以按性质把任务分为两类,macrotask(宏任务)和 microtask(微任务)。

  • 宏任务
    (macro)task(又称之为宏任务),可以理解是每次执行栈执行的代码就是一个宏任务(包括每次从事件队列中获取一个事件回调并放到执行栈中执行)。
    浏览器为了能够使得JS内部(macro)task与DOM任务能够有序的执行,会在一个(macro)task执行结束后,在下一个(macro)task 执行开始前,对页面进行重新渲染,流程如下:
    (macro)task->渲染->(macro)task->...
    
  • 微任务
    microtask(又称为微任务),可以理解是在当前 task 执行结束后立即执行的任务。也就是说,在 当前task任务后,下一个task之前,在渲染之前。所以它的响应速度相比setTimeout(setTimeout是task)会更快,因为无需等渲染。
    也就是说,在某一个macrotask执行完后,就会将在它执行期间产生的所有microtask都执行完毕(在渲染前)。
    microtask主要包含:Promise.then、MutaionObserver、process.nextTick(Node.js 环境)

它们的执行顺序如下:
在这里插入图片描述

在事件循环中,每进行一次循环操作称为tick,通过阅读规范可知,每一次 tick 的任务处理模型是比较复杂的,关键步骤总结如下:

  • 执行一个宏任务(栈中没有就从事件队列中获取)
  • 执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
  • 宏任务执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
  • 当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
  • 渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)

宏任务与微任务的优先级(浏览器):

  • macrotask(按优先级顺序排列): script(你的全部JS代码,“同步代码”), setTimeout, setInterval, setImmediate, I/O,UI rendering
  • microtask(按优先级顺序排列):process.nextTick,Promises(浏览器原生实现的 Promise), Object.observe, MutationObserver(await后面的代码,Promise.then里面的代码也属于微任务)
  • JS引擎首先从macrotask queue中取出第一个任务,执行完毕后,将microtask queue中的所有任务取出,按顺序全部执行;
  • 然后再从macrotask queue(宏任务队列)中取下一个,执行完毕后,再次将microtask queue(微任务队列)中的全部取出;
  • 循环往复,直到两个queue中的任务都取完。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章