Javascript 为什么我需要取消AnimationFrame()

Javascript 为什么我需要取消AnimationFrame(),javascript,animation,Javascript,Animation,我不明白为什么API包含cancelAnimationFrame(),因为 我可以通过如下设置continue变量来停止动画: function draw(timestamp) { if (continue == true) { requestAnimationFrame(draw); } } 所以问题是,在什么情况下我应该使用cancelAnimationFrame()?首先,这是一个重要的参考点。(日期)(候选推荐)规范: 与每个文档关联的是一个动画帧请求回调列表,它是一个元组列表。句

我不明白为什么API包含
cancelAnimationFrame()
,因为 我可以通过如下设置
continue
变量来停止动画:

function draw(timestamp) {
  if (continue == true) { requestAnimationFrame(draw); }
}

所以问题是,在什么情况下我应该使用cancelAnimationFrame()?

首先,这是一个重要的参考点。(日期)(候选推荐)规范:

与每个文档关联的是一个动画帧请求回调列表,它是一个元组列表。句柄是一个整数,它唯一地标识列表中的条目。回调是一个FrameRequestCallback对象。最初,文档的动画帧请求回调列表为空

另外,让我们记住,这些规范的目标受众是用户代理开发人员。正是在这些规范的实现中,用户代理为我们(应用程序开发人员)提供了一个API来与/进行交互

注意上面的每一份文件;您可以在
窗口
上下文中使用多表文档。一个浏览上下文中可以有多个上下文

那么,这与每个文档有什么关系呢?好的,(推荐)规范引用了流程模型,它实质上是将所有这些列表转储到一个空列表中,并对“保留”列表的结果执行回调调用算法。。但是,作为应用程序开发人员,这可能不是我们所关心的问题*我认为,作为应用程序开发人员,我们不会在自己的
窗口
上下文的多个文档中跟踪和维护Document.FrameRequestList实例。我们只是与API接口,可以在
窗口中访问该API

现在,让我们总结一下
requestAnimationFrame()
实际上做了什么,以及它返回了什么

调用
requestAnimationFrame
并提供
函数作为回调,在动画帧请求回调列表中添加条目
requestAnimationFrame
返回
处理程序[long]

根据上述规范()

cancelAnimationFrame方法用于取消先前发出的安排动画帧更新的请求

可以推断,通过调用
cancelAnimationFrame
并提供(可能以前存储的)
句柄作为参数,可以动画帧请求回调列表中删除项,,但情况并非如此

调用cancelAnimationFrame(handle)时,用户代理必须为此文档注册的回调将cancelled标志设置为true,该文档的句柄为handle。无论回调是否在动画帧请求回调列表中,都会设置取消标志。如果没有具有给定句柄的回调,则此函数不执行任何操作

因此,您在
cancelAnimationFrame
中提供的
句柄不会修改列表。它将取消标志设置为true“在回调时”。。这真的让它无法运行。这是合理的,因为前面提到的(以上)处理模型


因此,对于您的问题(以及关于您问题的特定评论),跳过向文档的动画帧请求回调列表添加条目,使用
requestAnimationFrame
不会保留现有
预定的
条目(或取消标志为false的现有条目)从跑步开始。有一个更大的上下文和处理模型要考虑(包括文档页面可见性属性)。 在您的问题中,有人提到您可能希望取消时间表框架请求的特定场景,但这样做的更好理由是出于无意的方面和考虑


简而言之,如果要使用API请求执行回调的帧更新,请使用API取消/停止所述更新请求并停止回调。

FWIW并完成接受的答案:

我来这里是想知道一个使用
requestAnimationFrame
调度的函数是否会抛出一个错误,该函数在执行时会对已经从DOM中删除(即卸载)的元素进行变异。没有,即:

let el=document.getElementById('element');
setTimeout(()=>el.remove(),20);
设置超时(()=>{
el.style.transform='比例(2)'
log(el instanceof HTMLElement)//el保存在内存中,但从DOM中删除
,40)//true`。

总之,您应该使用
cancelAnimationFrame
来防止使用
requestAnimationFrame
自动调度的函数产生副作用,并且您可以选择使用它来(micro-)即使没有副作用,也要通过避免执行来进行优化。

api背后的概念是向设备传达意图。我怀疑这是在这些方面。您的代码演示了如何有条件地安排下一个动画帧,而不是如何取消先前安排的动画回调。可能会出现一些情况(例如,当用户触发另一个互斥动画时),您可能希望在调度新的动画回调之前取消挂起的动画回调(类似于jQuery的
stop()
方法)。