背景:
使用setInterval或setTimeout时,我们会收到一个Id来取消/清除操作。
的setInterval / setTimeout的:
const timeoutId = setTimeout(() => {clearTimeout(timeoutId)}, 1000);
const intervalId = setInterval(() => {clearInterval(intervalId)}, 1000);
requestAnimationFrame:当使用raf时,对于步骤的每次迭代,我们重置rafId,我们只在最新的rafId上调用cancelAnimationFrame?
let rafId;
function step(timestamp) {
rafId = requestAnimationFrame(step);
console.log(timestamp, rafId)
if(timestamp >= 1000) {
cancelAnimationFrame(rafId);
}
}
rafId = requestAnimationFrame(step);
问题:当rafId
不断更新时,cancelAnimationFrame如何知道关闭所有先前对requestAnimationFrame的调用?
我猜想cancelAnimationFrame可以在frameId下运行并关闭它后面的所有内容。
如果这是真的,它如何与多个requestAnimationFrames
一起工作(因为它们将共享一个frameIds)
确实,requestAnimationFrame返回的id不断增加一个 - 但这并不重要。要保持请求“活动”,您需要在回调中重新请求它。让我们看看最后一次触发回调函数步骤会发生什么:
function step(timestamp) {
console.log("before " + rafId);
rafId = requestAnimationFrame(step);
console.log("after " + rafId);
if (timestamp >= 1000) {
cancelAnimationFrame(rafId);
}
}
rafId = requestAnimationFrame(step);
如果你查看控制台中的最后两行,它是这样的:
50岁之前
51之后
这意味着从最后一个回调返回的id已经是50,现在我们正在请求一个新的动画帧,它获得了id 51.这次虽然我们的if条件是真的,所以它取消了对id 51的请求。在调用回调函数时,id 50已经完成,因此无需取消它。