侧边栏壁纸
  • 累计撰写 47 篇文章
  • 累计创建 2 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

性能优化:用requestAnimationFrame封装setTimeOut

function setTimeoutRAF(callback, delay) {
    const startTime = performance.now();
    let animationFrameId = null;
    
    function loop(currentTime) {
        const elapsed = currentTime - startTime;
        
        if (elapsed >= delay) {
            callback();
        } else {
            animationFrameId = requestAnimationFrame(loop);
        }
    }
    
    animationFrameId = requestAnimationFrame(loop);
    
    // 返回一个清除函数
    return function clearTimeoutRAF() {
        if (animationFrameId) {
            cancelAnimationFrame(animationFrameId);
        }
    };
}

// 使用示例
const clearTimer = setTimeoutRAF(() => {
    console.log('延迟 2000ms 执行');
}, 2000);

// 取消定时器
// clearTimer();
注意

实际延迟时间可能会有微小偏差(± 几毫秒)

在后台标签页中,requestAnimationFrame 会暂停执行

对于精确时间要求不高的场景,原生 setTimeout 可能更合适

在处理需要大于 1 帧时长(60 帧=1/60s)的任务时会造成阻塞

优势对比
  1. 动画效果

    可能丢帧、卡顿

    更平滑,与刷新率同步

  2. 后台标签页

    继续执行(可能累积)

    自动暂停,节省资源

  3. 电池寿命

    可能更耗电

    浏览器优化,更省电

  4. 60fps 需求

    时间不精确

    天然适配 60fps

应用场景

适用涉及动画、视觉变化、布局更新的场景

  1. 批量 DOM 操作:将多个 DOM 更新延迟到同一帧
setTimeoutRAF(() => {
    // 批量执行DOM修改,减少重排
    element1.style.width = '100px';
    element2.style.height = '200px';
}, 100);
  1. 懒加载和分片加载
// 分片渲染大数据
function renderChunkedData(data, chunkSize = 100) {
    let index = 0;
    
    function renderNextChunk() {
        const chunk = data.slice(index, index + chunkSize);
        renderToDOM(chunk);
        index += chunkSize;
        
        if (index < data.length) {
            setTimeoutRAF(renderNextChunk, 0); // 下一帧继续
        }
    }

	function renderToDOM(chunk) {
		//DocumentFragment文档片段插入
	}
    
    renderNextChunk();
}
0

评论区