动画帧队列 vs 微任务队列

animation frame queue vs micro task queue

我猜microTask是在任何步骤中处理的。

我测试了这些东西,但我不确定我的假设是否正确。

测试 1 - macroTask 和 microTask

for (let i = 0; i < 2; i += 1) {
  setTimeout(() => {
    console.log('-- macro --')
    queueMicrotask(() => console.log('** micro **'));
  });
}

结果

-- macro --
** micro **
-- macro --
** micro **

测试 2 - microTask 和动画帧

for (let i = 0; i < 3; i += 1) {
  requestAnimationFrame(() => {
    console.log('@@ animation callback @@');
    queueMicrotask(() => {
      console.log('** micro **');
    });
  });
}

结果

@@ animation callback @@
** micro **
@@ animation callback @@
** micro **
@@ animation callback @@
** micro **

当我第一次看到这个测试结果时,我很惊讶。因为我认为动画帧队列中的所有任务都会被一次性处理。

但是,现在我觉得”在处理动画帧回调函数的时候,检查microTaskQueue是否为空,如果里面有任务,就处理它,调用下一个动画帧回调(由 requestAnimationFrame 函数插入。"

我说的对吗,还是我漏掉了什么重要的东西?

每次 JS 调用堆栈为空时都会访问微任务队列,作为 clean after running a script 的一部分。

  1. If the JavaScript execution context stack is now empty, perform a microtask checkpoint.

这一步是在所有animation callback execution, from the invoke算法之间输入的。

请注意,event-loop 处理也有几个 hard-coded 微任务检查点,例如在 step 7,但也在其他回调执行中。