对于debounce/throttle使用requestAnimationFrame而不是setTimeout有什么好处

Is there any advantage to using requestAnimationFrame instead of setTimeout for debounce/throttle

本文关键字:setTimeout 什么 debounce throttle 使用 requestAnimationFrame 对于      更新时间:2023-09-26

我在MDN上遇到过这个使用requestAnimationFrame而不是setTimeout的例子:

// Reference: http://www.html5rocks.com/en/tutorials/speed/animations/
var last_known_scroll_position = 0;
var ticking = false;
function doSomething(scroll_pos) {
  // do something with the scroll position
}
window.addEventListener('scroll', function(e) {
  last_known_scroll_position = window.scrollY;
  if (!ticking) {
    window.requestAnimationFrame(function() {
      doSomething(last_known_scroll_position);
      ticking = false;
    });
  }
  ticking = true;
});

这让我思考我们是否可以用requestAnimationFrame代替setTimeout(fn, 0),如果有什么好处?我在谷歌上搜索过,似乎所有的比较都是在动画的背景下完成的,但是不相关的功能呢?比如debounce/throttle或者只是如果你需要在重绘后运行代码?

RequestAnimationFrame是很好的,如果你想确保你没有做不必要的工作,因为你改变了一些东西在两个帧更新之间两次。

就其本身而言,requestAnimationFrame对动画之外的任何东西都没有用处,因为它只能等待16.666毫秒(如果没有延迟),因此您需要将多个链接在一起。但是如果你将它与setTimeout配对,那么你将能够等待特定的毫秒数,并确保你在正确的时间内绘制所有内容。

requestAnimationFrame在浏览器处于重新绘制步骤时调用。所以从理论上讲,如果你试图同步元素的属性(比如位置)和滚动位置,它应该可以避免闪烁/抖动。

setTimeout将在至少n毫秒之后被调用,所以你的回调可能会在下一次重画之前被调用多次,你会浪费CPU的使用,或者多次连续的重画发生而没有调用回调,这将导致闪烁/抖动,如果你试图同步元素的属性与滚动位置。

除了以上答案,

当使用requestAnimationFrame时,你的动画只会在选项卡(或窗口)对用户可见时运行。这意味着更少的CPU, GPU和内存的使用,因此电池友好。这对于通常电池寿命相对较短的移动设备尤其重要。

但是对于流畅的动画,我们必须注意我们的帧渲染发生在少于16ms,所以回调应该尽可能小的60 fps动画