看看下面的代码输出什么
如果你把上面的代码复制到浏览器的控制台, 输出结果应该是2 1 , 为什么?
按照常规的宏任务和渲染的理解, requestAnimationFrame 和 setTimeout 都是宏任务, 浏览器的执行顺序是 requestAnimationFrame -> 渲染(render) -> setTimeout, 输出的结果应该是 1 2 才对
这就要说到一个重点, 那就是宏任务和宏任务之间不一定会发生渲染, 浏览器会判断是否需要渲染, 即便是你在前一个宏任务里面更改了 dom 元素的属性, 也不一定会在下一个宏任务触发前发生渲染, 而 requestAnimationFrame 一定是伴随着渲染而触发的, 没有渲染就不会触发 requestAnimationFrame
浏览器真实的执行顺序是 宏任务 -> 微任务队列清空 -> 判断是否执行渲染 -> 需要渲染 ? requestAnimationFrame 宏任务触发 + 微任务队列清空 + 渲染
通过下面的例子,能更直观的理解这个过程
右边的示例, 每次点击 div 元素的时候, 都会调用 requestAnimationFrame 和 setTimeout
多次点击 div 后, 你会发现大部分的输出的都是 2 1
加上一段代码, 每次点击都会更新 dom 的宽度, 你会发现输出大部分都是 1 2,只有少部分的 2 1
这是因为浏览器要发生频繁的渲染, 伴随着 requestAnimationFrame 的触发比 setTimeout 更加快, 但是浏览器仍然会跳过一些渲染