使用requestIdleCallback和requestAnimationFrame优化前端性能

使用requestIdleCallback和requestAnimationFrame优化前端性能

🤔 为什么需要性能优化API?

在前端开发中,我们经常需要处理各种任务:DOM渲染、数据计算、网络请求等。如果这些任务处理不当,就会导致页面卡顿、响应缓慢,影响用户体验。

想象一下:用户正在滚动页面,同时我们的代码正在执行一个复杂的计算任务。这可能会导致页面卡顿,因为JavaScript是单线程的,复杂计算会阻塞主线程。

浏览器提供了两个强大的API来帮助我们优化这种情况:

  • requestAnimationFrame:在下一次浏览器重绘之前执行任务
  • requestIdleCallback:在浏览器空闲时间执行任务

这两个API可以帮助我们更合理地安排任务执行时间,避免阻塞主线程,提升页面流畅度。

💡 基础概念

1. requestAnimationFrame

requestAnimationFrame是浏览器提供的一个API,它允许我们在下一次浏览器重绘之前执行回调函数。浏览器通常以60fps(每秒60次)的频率进行重绘,所以requestAnimationFrame的回调大约每16.7ms执行一次。

应用场景

  • 动画效果(如平滑滚动、进度条动画)
  • 需要与页面渲染同步的任务
  • 避免不必要的重绘和回流

2. requestIdleCallback

requestIdleCallback是浏览器提供的另一个API,它允许我们在浏览器空闲时间执行回调函数。浏览器空闲时间是指:

  • 没有更高优先级的任务需要执行
  • 一帧的渲染工作已经完成,还有剩余时间

应用场景

  • 低优先级任务(如日志记录、数据上报)
  • 批量处理大量数据
  • 预加载非关键资源
  • 避免影响用户交互的任务

🚀 基础实现

1. requestAnimationFrame 示例:平滑滚动

// 平滑滚动到页面顶部
function smoothScrollToTop() {
   
   
  const startPosition = window.pageYOffset;
  const targetPosition = 0;
  const distance = targetPosition - startPosition;
  const duration = 800; // 动画持续时间(毫秒)
  let startTime = null;

  // 动画函数
  function animation(currentTime) {
   
   
    if (startTime === null) startTime = currentTime;
    const timeElapsed = currentTime - startTime;
    const progress = Math.min(timeElapsed / duration, 1);
    // 使用缓动函数让动画更自然
    const easeInOutQuad = progress < 0.5 ? 2 * progress * progress : -1 + (4 - 2 * progress) * progress;
    
    window.scrollTo(0, startPosition + distance * easeInOutQuad);
    
    if (timeElapsed < duration) {
   
   
      requestAnimationFrame(animation);
    }
  }

  requestAnimationFrame(animation);
}

// 使用示例
document.getElementById('scrollToTopBtn').addEventListener('click', smoothScrollToTop);

2. requestIdleCallback 示例:批量处理数据

// 需要处理的大量数据
const largeData = Array.from({
   
    length: 10000 }, (_, i) => i + 1);
const batchSize = 100; // 每批处理的数据量
let index = 0;

// 处理单个数据项的函数
function processItem(item) {
   
   
  // 模拟复杂处理逻辑
  console.log(`处理数据项: ${
     
     item}`);
  return item * 2;
}

// 使用requestIdleCallback批量处理数据
function processDataInBatches(deadline) {
   
   
  // 只要浏览器有空闲时间且还有数据需要处理
  while (deadline.timeRemaining() > 0 && index < largeData.length) {
   
   
    processItem(largeData[index]);
    index++;
    
    // 每处理batchSize个数据项,检查一次时间
    if (index % batchSize === 0) {
   
   
      console.log(`已处理 ${
     
     index} 个数据项`);
      break;
    }
  }
  
  // 如果还有数据需要处理,继续请求空闲时间
  if (index < largeData.length) {
   
   
    requestIdleCallback(processDataInBatches
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值