滚动事件上带有 clearAnimationFrame 的 requestAnimationFrame

requestAnimationFrame with clearAnimationFrame on scroll event

已经有很多关于 JavaScript 的 requestAnimationFrame 的问题,(我认为)我理解这个概念,但是在这个中有和没有 cancelAnimationFrame 之间是否存在任何性能差异上下文?

// Setup a timer
var timeout;

// Listen for resize events
window.addEventListener('scroll', function () {

    console.log( 'no debounce' );

    // Cancel last animation, if there's one
    if (timeout) {
        window.cancelAnimationFrame(timeout);
    }

    // Setup the new requestAnimationFrame()
    timeout = window.requestAnimationFrame(function () {

        // Run our scroll functions
        console.log( 'debounced' );

    });

}, false);

没有cancelAnimationFrame

// Setup a timer
var timeout;

// Listen for resize events
window.addEventListener('scroll', function () {

    console.log( 'no debounce' );


    // Setup the new requestAnimationFrame()
    window.requestAnimationFrame(function () {

        // Run our scroll functions
        console.log( 'debounced' );

    });

}, false);

我在每个代码上得到相同的结果。

但是我想知道如果我不取消动画帧会发生什么。请求的函数是否堆叠在内存中的某处或其他地方?

var isRafLogged = false;

function rafCb(now) {
  if (isRafLogged) {
    console.log('rAF callback executed at: ', now, 'ms');
  }
  requestAnimationFrame(rafCb);
}

function onWindowScroll() {
  // when in scroll, log aforescheduled rAF() only when in scroll
  isRafLogged = true;
  const now = performance.now();

  console.log('scroll callback executed at: ', now, 'ms');

  // when out of scroll, stop logging the rAF
  setTimeout(function() {
    isRafLogged = false;
  });
}

requestAnimationFrame(rafCb);

window.addEventListener('scroll', onWindowScroll);
html,
body {
  height: 10000px;
}

p {
  font-size: 200px;
  writing-mode: vertical-lr;
}
<p>.....................................................................................................................................................................................................................................................................................................................................................................</p>

如果我们在 scroll 时安排一个连续的单独 requestAnimationFrame 循环,我们将清楚地看到 rAFscroll 回调正在发生 每 VSync event.

最多一次

回到你的主要问题

is there any performance difference between with and without cancelAnimationFrame in this context ?

通常不会,因为您的 requestAnimationFrame() 调用会阻止下一个 scroll 回调,并且您执行的滚动回调不能多于请求的帧回调,因此存在 1 比 1 的相关性,因为它们都发生在每帧渲染的最大值。

But I want to know what happens if I don't cancel the animation frame. Does requested function get stacked somewhere in memory or something?

所有请求的动画帧回调都堆叠在 callbacks 的内部池中,在最近的 Vsync 事件之前被刷新。所以是的,从技术上讲,删除预定回调的唯一方法是 cancelAnimationFrame(),但它与您的情况无关,因为您的 requestAnimationFrame() 回调发生在 "same" 时间 window scroll回调。

希望它有意义。