【问题标题】:Any advantages of using requestAnimationFrame for non-animation purposes?将 requestAnimationFrame 用于非动画目的有什么好处?
【发布时间】:2021-01-13 10:05:23
【问题描述】:

我做了一个“睡眠”定时器函数,它递归调用 requestAnimationFrame 并在时间用完后返回一个 promise。我使用 requestAnimationFrame 是否有任何性能优势,或者我应该只使用 setTimeout?我知道 requestAnimationFrame 在非常短/快速的等待时间(也称为动画帧)上具有更好的性能,但是对于接近或超过一秒的等待时间,它有什么不同吗?

var sleep = (time) =>{
  var timer = (t, s, d, r)=>{
    if(t - s > d){
      r("done")
    } else {
      requestAnimationFrame((newT)=>{ timer(newT, s, d, r)})
    }
  }
  return new Promise((r)=>{
    requestAnimationFrame((t)=>{timer(t, t, time, r)})
  })
}

(async ()=>{
  var message = document.getElementById("message")
  while(message){
    message.innerText = "Get"
    await sleep(1000)
    message.innerText = message.innerText + " Ready"
    await sleep(1000)
    message.innerText = message.innerText + " To"
    await sleep(1000)
    message.innerText = message.innerText + " Wait"
    await sleep(1000)
  }
})()
<p style="text-align:center; font-size:20px;" id="message"></p>

【问题讨论】:

  • 是的,您绝对应该使用setTimeout,它用于计时(包括睡眠)而不是用于动画。 requestAnimationFrame 解决方案的性能要差得多,因为您必须重复调用它,从而降低您的函数效率。
  • 很高兴知道。谢谢!

标签: javascript timer async-await settimeout requestanimationframe


【解决方案1】:

requestAnimationFrame 不仅仅是一种计时方法,正如它的名字所说,它还请求一个动画帧。

在浏览器中,event loop processing model 确实首先执行正常任务,然后,when the browser thinks it should update the rendering,它调用这个处理模型的一个特殊部分,update the rendering

在大多数事件循环迭代中,进入处理模型的这个可选部分所需的条件不满足,因此不进行渲染,这很好,因为渲染成本很高。

尽管规范留给实施者选择他们将使用什么启发式方法来决定何时更新渲染,但大多数人还是会使用显示器的刷新率作为基本频率。
除了此监视器的刷新事件外,它们仅更新它们标记为需要更新的文档的呈现。
大多数时候,一个网页不需要重新渲染,只有在动画运行时,或者当用户与之交互时,他们才会将文档标记为需要重新渲染.

requestAnimationFrame是我们web-devs在这次更新渲染子流程中hook的一个工具,让我们只有在要渲染的时候才能绘制东西,但它也有将网页标记为的副作用动画,从而强制浏览器执行完整的更新渲染步骤,即使它可能不需要。

例如,使用 Chrome 的 Performance 开发工具,您可以在下面的 sn-p 中看到一个简单的空 rAF 循环将导致 复合层 操作在每次屏幕刷新时触发,而它会仅当鼠标移动时才会发生,并且只是因为 mouse-move 在内部调用 rAF)。

const input = document.querySelector("input");
input.oninput = (evt) => {
  rAFLoop();
};
function rAFLoop() {
  if( input.checked ) {
    requestAnimationFrame( rAFLoop );
  }
}
<label><input type="checkbox" id="inp">activate rAF loop</label>

因此,虽然requestAnimationFrame 是视觉动画的绝佳工具,但它也有责任,就你而言,你在滥用它。

使用简单的setTimeout 是可行的方法,不仅它与渲染过程没有任何关系,而且如果没有其他任何事情发生,它甚至可以让浏览器进入 idle ,让您的计算机执行其他任务,或保护树木。

const sleep = (ms) =>
  new Promise( (res) =>
    setTimeout( () => res(), ms )
  );
(async ()=>{
  var message = document.getElementById("message")
  while(message){
    message.innerText = "Get"
    await sleep(1000)
    message.innerText = message.innerText + " Ready"
    await sleep(1000)
    message.innerText = message.innerText + " To"
    await sleep(1000)
    message.innerText = message.innerText + " Wait"
    await sleep(1000)
  }
})()
<p style="text-align:center; font-size:20px;" id="message"></p>

【讨论】:

  • 谢谢。是的,当我看到上面的第一条评论时,我将其更改为 setTimeout,就像您拥有它一样。
猜你喜欢
  • 1970-01-01
  • 2017-03-09
  • 2013-10-18
  • 2022-08-05
  • 2019-05-08
  • 2019-06-09
  • 2015-11-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多