长时间运行的超时回调阻止了requestAnimationFrame回调的执行

时间:2018-09-07 20:42:59

标签: javascript callback timeout requestanimationframe event-loop

我看过Jake Archibald talk about event loop,发现浏览器中有3个队列:

  • 回叫队列
  • 微任务队列
  • 动画队列

在执行其项目时的行为有所不同。

回叫队列一次执行一次回叫,这意味着执行回叫后,浏览器在继续下一个之前要检查是否还有其他事情(例如重新渲染页面)。

微任务队列执行其项目,直到队列为空(这可能导致无限阻塞)

动画队列用于requestAnimationFrame回调,并且它会执行其项,直到队列为空,除了在当前执行的回调之一(这些回调在下一帧中执行)中添加的回调之外。

我想检查一下并创建了一个脚本,该脚本递归调用requestAnimationFrame并排队了50个超时回调,这些回调将主线程阻塞了15ms。

for (let i = 0; i < 50; i++) {
  setTimeout(() => {
    block(15);
    console.log(`timeout ${i}`)
  })
}

const startDate = Date.now();
function raf() {
  requestAnimationFrame((x) => {
    if (Date.now() < startDate + 1000) {
      console.log(`raf ${x}`)
      raf();
    }
  })
}

raf();



function block(ms) {
  const startDate = Date.now();
  while (Date.now() < startDate + ms) { }
}

实时演示:https://stackblitz.com/edit/js-xdpbbb?file=index.js

由于块时间大致等于帧之间的时间(60fps给出16.666ms),所以我期望raf和超时回调之间存在交织的模式。但是结果却完全不同:

results

您可以看到raf回调之间大约有10个超时回调,大约需要150毫秒才能完成。为什么不这样:

  1. 超时cb
  2. 动画cb
  3. 超时cb
  4. 动画cb ?

0 个答案:

没有答案