滚动事件上带有 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
循环,我们将清楚地看到 rAF
和 scroll
回调正在发生
每 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
回调。
希望它有意义。
已经有很多关于 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
循环,我们将清楚地看到 rAF
和 scroll
回调正在发生
每 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
回调。
希望它有意义。