RIC
requestIdleCallback()
(RIC) 是一种浏览器 API,它可以在浏览器空闲时执行回调函数。由于它不会阻塞主线程,因此可以用于执行一些后台任务或预加载资源,以避免阻塞用户界面
基本语法
jswindow.requestIdleCallback(callback[, options]);
其中,callback 是要运行的函数,options 是一个可选参数对象,可以设置回调函数的超时时间和调度优先级。例如:
jswindow.requestIdleCallback(function() { console.log('这是一个任务'); }, { timeout: 2000 });
requestIdleCallback 的返回值是一个 ID,可以用于取消任务:
jsconst requestId = window.requestIdleCallback(function() { console.log('这是一个任务'); }); window.cancelIdleCallback(requestId);
requestIdleCallback()
是一个浏览器 API,可以在主线程空闲时运行回调函数。这使得我们可以在不影响页面流畅性的情况下执行一些较重的操作。在优化 document.addEventListener 监听 scroll 事件时,可以使用 requestIdleCallback() 来推迟处理滚动事件,以减少滚动事件的处理次数。
tsximport { useEffect, useRef } from 'react'; function handleScroll() { // 处理滚动事件 } function useRequestIdleScroll() { const tickingRef = useRef(false); function requestTick() { if (!tickingRef.current) { requestIdleCallback(() => { handleScroll(); tickingRef.current = false; }); tickingRef.current = true; } } useEffect(() => { document.addEventListener('scroll', requestTick); return () => { document.removeEventListener('scroll', requestTick); }; }, []); } function App() { useRequestIdleScroll(); // 渲染组件 }
ts//useRequestIdleScroll.ts import {useEffect, useRef} from "react"; function useRequestIdleScroll(handler: () => void) { const tickingRef = useRef(false); function requestTick() { if (!tickingRef.current) { requestIdleCallback(() => { handler(); tickingRef.current = false; }); tickingRef.current = true; } } useEffect(() => { document.addEventListener('scroll', requestTick); return () => { document.removeEventListener('scroll', requestTick); }; }, []); } export default useRequestIdleScroll
RAF
requestAnimationFrame
(RAF) 是一种浏览器 API,它可以在浏览器下一次重绘之前执行回调函数。由于它与浏览器的渲染循环同步,因此在使用动画或其他需要频繁更新的元素时非常有用。
jswindow.requestAnimationFrame(callback);
其中,callback 是要运行的函数。该函数应该负责更新动画或其他页面元素,然后在下一次重新渲染页面之前再次调用 requestAnimationFrame。
jsfunction animate() { // 更新动画 window.requestAnimationFrame(animate); } animate();
requestAnimationFrame 的返回值是一个 ID,可以用于取消动画:
jsconst animationId = window.requestAnimationFrame(function() { // 更新动画 }); window.cancelAnimationFrame(animationId);
常见场景
-
动画:
requestAnimationFrame
是最常见的用例之一。通过在每个动画帧上更新元素的位置或样式,可以创建流畅的动画效果。使用requestAnimationFrame
可以避免使用setInterval
或setTimeout
导致的不同步和性能问题。 -
游戏:
requestAnimationFrame
也非常适合用于游戏开发。在每个游戏循环中使用requestAnimationFrame
更新游戏状态和元素位置可以确保游戏的流畅度和响应性。 -
滚动:通过
requestAnimationFrame
更新页面的滚动位置,可以创建平滑的滚动效果,而不会出现卡顿或闪烁的情况。这在单页应用程序或长页面中非常有用。使用requestAnimationFrame()
仍然可能会导致滚动事件处理函数的频率过高。因此,在实际应用中进行性能测试和调优非常重要,以确保代码可以在各种情况下正常运行 -
图表:使用
requestAnimationFrame
可以在每个动画帧上更新图表的数据和样式,从而创建动态的、实时的图表效果。 -
视频播放器:使用
requestAnimationFrame
可以在每个动画帧上更新视频的时间戳和播放状态,从而创建流畅的视频播放效果。
需要注意的是,requestAnimationFrame 的回调函数应该尽可能快地执行完毕,以确保动画的流畅度和响应性。如果需要执行更长时间的任务,可以将它们拆分为多个小任务,并使用 requestIdleCallback 在空闲时运行它们。
区别
requestIdleCallback
和 requestAnimationFrame
都是用于浏览器性能优化的 API,但它们的作用不同。requestIdleCallback
用于在浏览器空闲时运行任务,例如后台工作或预加载资源。requestAnimationFrame
则用于在每次重新渲染页面时更新动画或其他需要频繁更新的元素。
此外,requestIdleCallback
和 requestAnimationFrame
在性能和使用方面也有一些区别:
-
性能:
requestIdleCallback
可以将任务拆分为多个小任务,因此它更适合执行耗时较长的任务。而requestAnimationFrame
的回调函数应该尽可能快地执行完毕,以确保动画的流畅度。 -
兼容性:
requestIdleCallback
是一个比较新的 API,尚未被所有浏览器支持。而requestAnimationFrame
已经被广泛支持,可以在大多数现代浏览器中使用。 -
使用:
requestIdleCallback
可以用于执行后台任务或预加载资源,以避免阻塞用户界面。而requestAnimationFrame
适用于在页面中创建流畅的动画或其他需要频繁更新的元素。
使用建议
在实际项目中,我们可以根据具体场景来选择使用 requestIdleCallback
和 requestAnimationFrame
。一般来说,我们应该优先选择 requestAnimationFrame 来更新动画或其他频繁更新的元素,以确保流畅度和性能。而对于一些后台任务或预加载资源,我们可以使用 requestIdleCallback 来避免阻塞用户界面。
另外,我们还可以结合使用这两个 API,例如在页面中创建复杂的动画时,我们可以使用 requestAnimationFrame
更新动画,同时在动画之外使用 requestIdleCallback
来执行一些后台任务或预加载资源,以提高用户体验。
总结
requestIdleCallback
和 requestAnimationFrame
都是用于浏览器性能优化的 API。requestIdleCallback
可以在浏览器空闲时运行任务,例如后台工作或预加载资源,而 requestAnimationFrame
则用于在每次重新渲染页面时更新动画或其他需要频繁更新的元素。在使用时,我们应该根据具体场景选择合适的 API,同时结合使用它们以提高用户体验。