加载中...

Eventloop,requestIdlecallback 和 requestAnimationFrame的理解


🔁 一、Event Loop(事件循环)

🌟 概念核心:

JS 是单线程的,但为了不阻塞主线程,它采用了 异步非阻塞的执行模型,即:Event Loop

👇 工作流程简要版:

  1. Call Stack(调用栈):同步代码进来就执行,执行完出栈。
  2. Web APIs:定时器、DOM 事件、XHR 等异步操作会交给浏览器处理。
  3. Callback Queue(任务队列)
    • 宏任务(Macro Task):如 setTimeoutsetIntervalsetImmediateI/OrequestIdleCallback
    • 微任务(Micro Task):如 Promise.thenMutationObserver
  4. Event Loop 会不断循环:
    • 清空调用栈
    • 执行所有微任务
    • 执行一个宏任务
    • 再次检查微任务
    • 如此反复…

📌 一句话理解:Event Loop 是让异步代码按顺序执行的调度机制。

🧘‍♂️ 二、requestIdleCallback(callback)

📍 作用:

用于在浏览器空闲时执行一些不重要、可延迟的任务,比如预加载、统计分析、懒加载等。

✅ 特点:

  • 会在主线程空闲时调用,不影响页面流畅度。
  • callback(deadline)deadline.timeRemaining() 表示当前剩余空闲时间,最大 50ms。
  • 可以设置 timeout 防止永远不执行。

🎯 适合做什么?

  • 页面加载完后,处理缓存、预加载资源、打点统计。
  • 渲染不相关的长任务(可以切片)。
requestIdleCallback((deadline) => {
  while (deadline.timeRemaining() > 0 && tasks.length > 0) {
    performTask(tasks.shift());
  }
});

🧊 三、requestAnimationFrame(callback)

📍 作用:

让 JS 在下一帧渲染前执行,专用于视觉动画相关的逻辑。

✅ 特点:

  • 每秒最多执行一次,跟屏幕刷新率(一般是 60Hz)同步。
  • 优化动画:在浏览器准备绘制之前运行 callback,不会掉帧。
  • 会在下次“重绘”前被调用,适合更新 UI 的操作。

🎯 适合做什么?

  • 平滑动画(移动元素、canvas 绘图)
  • 渲染状态变化(比如滚动监听、进度条)
function update() {
  drawSomething();
  requestAnimationFrame(update); // 类似递归动画循环
}
requestAnimationFrame(update);

🧠 总结对比:

API 触发时机 适合场景 优先级
Event Loop 控制任务调度 所有异步执行逻辑 高(根本)
requestAnimationFrame 下一帧绘制前 UI 动画渲染 高(与屏幕刷新率同步)
requestIdleCallback 空闲时 后台逻辑、低优任务 低(不稳定)

💡 实战经验:

  • 动画用 requestAnimationFrame,不要用 setTimeout(fn, 16)
  • 后台任务别卡主线程,适合用 requestIdleCallback 处理碎片化逻辑。
  • 长任务要考虑切片执行 + 微任务调度防止掉帧。

文章作者: LYF
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LYF !
评论
  目录