真实面经题目 · 原创解析

requestAnimationFrame 属于什么任务,适合解决什么问题?

requestAnimationFrame 不是普通宏任务,也不是微任务,而是浏览器在一次渲染机会中、绘制之前执行的动画帧回调。它适合把视觉更新对齐到屏幕刷新节奏,用来做动画、滚动联动、分批 DOM 更新和避免 setTimeout 与刷新率不一致造成的卡顿。

出现于:字节跳动 · 前端

60 秒回答模板

requestAnimationFrame 可以理解为浏览器渲染流水线里的帧回调。事件循环会先执行一个宏任务,再清空微任务队列;当浏览器准备更新渲染时,会执行这一帧注册的 requestAnimationFrame 回调,然后进行样式计算、布局、绘制和合成。它的优势是回调时机接近下一次绘制,频率通常跟随屏幕刷新率,后台标签页会被降频或暂停,所以比 setTimeout 更适合视觉动画。它不能让耗时 JS 自动变快,长任务仍然会阻塞主线程;如果每帧做太多计算,仍然会掉帧。

考点 不是宏微任务
难度 真实面经高频题
回答目标 讲清机制、边界和追问

深入解析

01

任务归类

面试里常问 requestAnimationFrame 属于宏任务还是微任务,严谨回答是它不属于这两类常规任务队列。它是动画帧回调,运行在浏览器一次渲染更新之前。宏任务负责执行脚本、定时器、用户事件等,微任务负责 Promise 回调、MutationObserver 等;requestAnimationFrame 的调度点与渲染机会绑定,关注的是下一帧何时绘制。

02

执行时机

一次常见事件循环中,浏览器执行完当前任务后会清空微任务队列,然后在需要渲染时进入更新渲染流程。requestAnimationFrame 回调会在绘制前被调用,这使得代码可以在浏览器真正提交像素之前计算下一帧的样式状态。回调收到的时间戳也能用于基于时间差计算动画进度,而不是假设固定帧率。

03

动画优势

setTimeout(fn, 16) 只是大致延迟,并不保证和屏幕刷新同步;如果页面刷新率是 120Hz、标签页在后台、主线程繁忙或计时器被节流,实际时机都会偏离。requestAnimationFrame 由浏览器在合适的渲染机会触发,能减少无效绘制和帧间抖动。对于位移、缩放、透明度变化,它通常与 transform、opacity 组合使用。

04

性能场景

requestAnimationFrame 适合处理会影响视觉结果的高频更新,例如拖拽反馈、滚动位置同步、自定义进度条、canvas 绘制、DOM 读写批处理。一个常见优化是把多次事件触发合并成一帧更新:事件里只记录最新状态,如果这一帧尚未注册回调,再通过 requestAnimationFrame 统一刷新 UI。

05

边界限制

requestAnimationFrame 仍然运行在主线程,不能替代性能优化。如果回调里做大量计算、同步读取布局后又写布局、请求阻塞资源,仍然会错过一帧预算。后台标签页中回调可能暂停,不能用于可靠计时或业务轮询。计算密集任务应拆分、让出主线程,或者放到 Web Worker;业务定时任务仍应使用更合适的调度机制。

易错点

  • 把 requestAnimationFrame 简单归为宏任务,忽略它是渲染更新前的帧回调。
  • 认为使用 requestAnimationFrame 后动画一定流畅,没有考虑回调内部长任务。
  • 把它用于业务轮询或精准计时,忽略后台标签页节流和暂停。
  • 在回调里反复读取和写入布局属性,导致每一帧都出现强制同步布局。

面试官追问

requestAnimationFrame 和 setTimeout 做动画有什么区别?

setTimeout 只按计时器延迟触发,可能和屏幕刷新错开;requestAnimationFrame 由浏览器在下一次绘制前触发,更容易保持动画和刷新节奏一致,并且在后台标签页会自动节流。

requestAnimationFrame 回调里适合读布局还是写布局?

可以做视觉更新,但要避免读写交错。实践中通常先集中读取布局信息,再集中写入样式,或者把读取放在上一阶段,把写入放进 requestAnimationFrame,减少强制同步布局。

requestAnimationFrame 会在页面不可见时继续执行吗?

多数浏览器会对后台标签页中的 requestAnimationFrame 降频或暂停,以节省资源。因此它适合视觉更新,不适合作为可靠的后台计时器。

为什么一帧预算经常说是 16.7ms?

60Hz 屏幕一秒刷新约 60 次,一帧约 16.7ms。但这只是总预算,浏览器还要处理输入、样式、布局、绘制和合成,留给 JS 的时间通常更少;高刷新率屏幕预算会更短。