编程 前端任务调度实战:用 rAF + rIC 提升页面流畅度

2025-08-15 12:45:42 +0800 CST views 355

前端任务调度实战:用 rAF + rIC 提升页面流畅度

在前端开发中,长任务或大量 DOM 操作会阻塞主线程,导致页面掉帧。通过 rAFrIC,我们可以实现 高优先级任务与低优先级任务的合理调度


一、场景设定

假设我们有两个任务:

  1. 动画任务(高优先级):持续更新 UI 元素位置
  2. 数据处理任务(低优先级):处理一堆数据、日志或缓存计算

我们希望:

  • 动画流畅,不被阻塞
  • 数据处理在浏览器空闲时执行,不影响渲染

二、动画任务(高优先级)- rAF

const box = document.getElementById('box');
let position = 0;

function animate() {
  position += 2;
  if (position > 300) position = 0;

  box.style.transform = `translateX(${position}px)`;

  requestAnimationFrame(animate);
}

// 启动动画
requestAnimationFrame(animate);

✅ 特点:

  • 每帧调用一次动画函数
  • 与浏览器渲染同步,保证平滑动画

三、后台数据任务(低优先级)- rIC

// 假设有一堆数据需要处理
let tasks = Array.from({ length: 1000 }, (_, i) => i + 1);

function processTasks(deadline) {
  // 利用空闲时间处理任务
  while (deadline.timeRemaining() > 0 && tasks.length > 0) {
    const task = tasks.shift();
    console.log('处理任务', task);
  }

  // 如果任务未完成,预约下一次空闲时间继续
  if (tasks.length > 0) {
    requestIdleCallback(processTasks);
  }
}

// 启动空闲任务处理
requestIdleCallback(processTasks);

✅ 特点:

  • 每次只处理当前空闲时间内的任务
  • 大任务被分块执行,不阻塞动画
  • 自动让出主线程,保证用户体验

四、综合示例:动画 + 数据处理

<div id="box" style="width:50px; height:50px; background:red; position:absolute;"></div>
// 动画任务
const box = document.getElementById('box');
let position = 0;

function animate() {
  position += 2;
  if (position > window.innerWidth - 50) position = 0;
  box.style.transform = `translateX(${position}px)`;
  requestAnimationFrame(animate);
}

requestAnimationFrame(animate);

// 后台数据处理任务
let tasks = Array.from({ length: 5000 }, (_, i) => i + 1);

function processTasks(deadline) {
  while (deadline.timeRemaining() > 0 && tasks.length > 0) {
    const task = tasks.shift();
    // 模拟耗时计算
    Math.sqrt(task * 12345);
  }
  if (tasks.length > 0) {
    requestIdleCallback(processTasks);
  }
}

requestIdleCallback(processTasks);

效果演示:

  • 红色方块平滑移动,不掉帧
  • 数据处理分块执行,不阻塞动画

五、实战技巧

  1. 区分任务优先级:UI 渲染、动画用 rAF;日志、缓存、后台计算用 rIC
  2. 任务分块:大任务拆分成小块,通过 timeRemaining() 控制执行量
  3. 兼容性考虑:rIC 在某些老版本浏览器不可用,可 fallback 到 setTimeout
const requestIdleCallbackSafe = window.requestIdleCallback || function(fn) {
  return setTimeout(() => fn({ timeRemaining: () => 50 }), 0);
};

六、总结

  • rAF:高优先级视觉任务,保证动画流畅
  • rIC:低优先级后台任务,协作式调度,避免阻塞
  • 组合使用可实现 性能和用户体验双赢
  • 大任务分块处理 + 协作式调度 = 页面不卡顿
复制全文 生成海报 前端开发 性能优化 用户体验

推荐文章

Nginx 如何防止 DDoS 攻击
2024-11-18 21:51:48 +0800 CST
JavaScript设计模式:装饰器模式
2024-11-19 06:05:51 +0800 CST
Rust开发笔记 | Rust的交互式Shell
2024-11-18 19:55:44 +0800 CST
js一键生成随机颜色:randomColor
2024-11-18 10:13:44 +0800 CST
JavaScript 异步编程入门
2024-11-19 07:07:43 +0800 CST
php客服服务管理系统
2024-11-19 06:48:35 +0800 CST
在 Vue 3 中如何创建和使用插件?
2024-11-18 13:42:12 +0800 CST
程序员出海搞钱工具库
2024-11-18 22:16:19 +0800 CST
Elasticsearch 的索引操作
2024-11-19 03:41:41 +0800 CST
mysql 计算附近的人
2024-11-18 13:51:11 +0800 CST
如何在Vue3中定义一个组件?
2024-11-17 04:15:09 +0800 CST
Vue3中如何扩展VNode?
2024-11-17 19:33:18 +0800 CST
git使用笔记
2024-11-18 18:17:44 +0800 CST
Vue3如何执行响应式数据绑定?
2024-11-18 12:31:22 +0800 CST
PostgreSQL日常运维命令总结分享
2024-11-18 06:58:22 +0800 CST
CSS 实现金额数字滚动效果
2024-11-19 09:17:15 +0800 CST
使用临时邮箱的重要性
2025-07-16 17:13:32 +0800 CST
开发外贸客户的推荐网站
2024-11-17 04:44:05 +0800 CST
如何在 Linux 系统上安装字体
2025-02-27 09:23:03 +0800 CST
程序员茄子在线接单