乐趣区

关于javascript:笔记javascript事件循环

事件循环

事件循环 的流程大抵如下:

  1. 所有工作都在主线程上执行,造成一个执行栈。
  2. 主线程发现有异步工作,就在“工作队列”之中退出一个工作事件。
  3. 一旦“执行栈”中的所有同步工作执行结束,零碎就会读取“工作队列”(先进先出准则)。那些对应的异步工作,完结期待状态,进入执行栈并开始执行。
  4. 主线程一直反复下面的第三步,这样的一个循环称为事件循环。

宏工作 & 微工作

如果工作队列中有多个异步工作,那么先执行哪个工作呢?于是在异步工作中,也进行了等级划分,分为宏工作(macrotask)和微工作(microtask);不同的 API 注册的工作会顺次进入本身对应的队列中,而后期待事件循环将它们顺次压入执行栈中执行。

+ 宏工作包含

  1. script(整体代码)
  2. setTimeout, setInterval, setImmediate,
  3. I/O
  4. UI rendering
  5. requestAnimationFrame()
  • 微工作包含
  1. process.nextTick
  2. Promise
  3. Object.observe(已废除)
  4. MutationObserver(html5 新个性)

Node 事件循环

requestAnimationFrame

在没有 requestAnimationFrame 办法的时候,执行动画,咱们可能应用 setTimeoutsetInterval 来触发视觉变动;然而这种做法的问题是:回调函数执行的工夫是不固定的,可能刚好就在开端,或者间接就不执行了,常常会引起丢帧而导致页面卡顿。

归根到底产生下面这个问题的起因在于机会,也就是浏览器要晓得何时对回调函数进行响应。setTimeoutsetInterval 是应用定时器来触发回调函数的,而定时器并无奈保障可能准确无误的执行,有许多因素会影响它的运行机会,比如说:当有同步代码执行时,会先等同步代码执行结束,异步队列中没有其余工作,才会轮到本人执行。并且,咱们晓得每一次从新渲染的最佳工夫大概是 16.6 ms,如果定时器的工夫距离过短,就会造成适度渲染,减少开销;过长又会提早渲染,使动画不晦涩。

requestAnimationFrame 办法不同与 setTimeoutsetInterval,它是由零碎来决定回调函数的执行机会的,会申请浏览器在下一次从新渲染之前执行回调函数。无论设施的刷新率是多少,requestAnimationFrame 的工夫距离都会紧跟屏幕刷新一次所须要的工夫 。须要留神的是这个办法尽管可能 保障回调函数在每一帧内只渲染一次 ,然而 如果这一帧有太多任务执行,还是会造成卡顿的;因而它只能保障从新渲染的工夫距离最短是屏幕的刷新工夫。

requestIdleCallback

一些低优先级的工作可应用 requestIdleCallback 等浏览器不忙的时候来执行,同时因为工夫无限,它所执行的工作应该尽量是可能量化,细分的微工作(micro task)。

因为它产生在一帧的最初,此时页面布局曾经实现,所以不倡议在 requestIdleCallback 里再操作 DOM,这样会导致页面再次重绘。DOM 操作倡议在 rAF 中进行。同时,操作 DOM 所须要的耗时是不确定的,因为会导致从新计算布局和视图的绘制,所以这类操作不具备可预测性。

Promise 也不倡议在这外面进行,因为 Promise 的回调属性 Event loop 中优先级较高的一种微工作,会在 requestIdleCallback 完结时立刻执行,不论此时是否还有充裕的工夫,这样有很大可能会让一帧超过 16 ms。

退出移动版