requestAnimationFrame 和 setTimeout 区别

前言

对于现在技术社区的现状的,我分析用户画像 觉得大部分的用户更多的是喜欢短频快的节奏文章,所以故尝试用最短时间挖掘简单的面试题,将背后的知识整理分享给大家,喜欢在后续的面试过程中,可以对你有帮助,如果刚好是自己的知识盲区不妨帮忙点赞支持一下

背景

相信大部分的开发者都使用过 setTimeout 这个 API, 如果没有使用过可以,使用跳转地址setTimeout[1] 但是我相信很多开发者是没有使用过requestAnimationFrame 这个 API的,因为我们平时开发中几乎不需要用到,相信也有朋友在 React

下面我们分开介绍两个API,在正式开始之前我们不妨先学习一下如何使用 requestAnimationFrame

requestAnimationFrame

顾明思议,RequestAnimationFrame, 在动画帧请求做件事情,具体可以看科普文章[2]

window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行

语法

window.requestAnimationFrame(callback);

用法

一般用在操作动画帧上,在物体需要在一帧渲染之前执行某个动画。一般是更好的优化动画上

const element = document.getElementById('some-element-you-want-to-animate'); // 需要移动的物体元素

let start;

function step(timestamp) {
  if (start === undefined) start = timestamp;
    
  const elapsed = timestamp - start;

  //这里使用`Math.min()`确保元素刚好停在200px的位置。
  element.style.transform = 'translateX(' + Math.min(0.1 * elapsed, 200) + 'px)'; // 每次移动 0.1 * elapsed 时间

  if (elapsed < 2000) { // 在两秒后停止动画
    window.requestAnimationFrame(step); 
  }
}

window.requestAnimationFrame(step); // 执行动画

返回值

你没看错 requestAnimationFrame 是有返回值的。

一个 long 整数,请求 ID ,是回调列表中唯一的标识。是个非零值,没别的意义。你可以传这个值给 `window.cancelAnimationFrame()`[3] 以取消回调函数。

cancelAnimationFrame 调用参数是先前调用 window.requestAnimationFrame()方法时候返回的ID

setTimeout

下面介绍的 setTimeout 相信大部分的开发者都使用过这个API吧,而且可以说相当熟悉

语法

var timeoutID = scope.setTimeout(function[ , delay, arg1, arg2, ...]);
var timeoutID = scope.setTimeout(function[, delay]);
var timeoutID = scope.setTimeout(code[, delay]);

用法

用于延迟执行某个动作,或者可以循环调用自身,实现 setInterval 的效果,但注意需要释放 setTimeout 返回的 ID 利用clearTimeout 清空定时器。

var timeoutID;

function delayedAlert() {
  timeoutID = window.setTimeout(slowAlert, 2000);
}

function slowAlert() {
  alert('That was really slow!');
}

function clearAlert() {
  window.clearTimeout(timeoutID);
}

返回值

返回值timeoutID是一个正整数,表示定时器的编号。这个值可以传递给`clearTimeout()`[4]来取消该定时器。

这里有意思的点是 setTimeout()`setInterval()`[5]共用一个编号池,技术上,clearTimeout()和 `clearInterval()`[6] 可以互换。但是,为了避免混淆,不要混用取消定时函数。两者竟然是可以互换的

在同一个对象上(一个window或者worker),setTimeout()或者setInterval()在后续的调用不会重用同一个定时器编号。但是不同的对象使用独立的编号池。

两者对比

下面我们总结一下他们的差异


requestAnimationFrame setTimeout
语法 window.requestAnimationFrame(callback); setTimeout(callback, time)
用法 用于动画帧渲染时候,优化动画渲染场景中 用于延迟执行某个动作的场景中
返回值 正整数(用于后续 cancelAnimationFrame) 正整数 (用于后续 clearTimeout)
调用周期 0.2 ~ 0.3 ms (大约1帧的时间) 1 ~ 3 ms (setTimeout 第二个参数传入 0 情况下)

所以两者其实在时间上来理解的话,是在不同的调用周期中执行,setTimeout 是没有办法在 0.2 ~ 0.3 ms范围内执行某个回调的,这里我们提到时间范围的概念,这里就不得不提到 setTimeout 最小延迟时间的概念

setTimeout 最小延迟时间

console.time('ok')
setTimeout(() => {console.timeEnd('ok')}, 0); // ok: 1.93115234375 ms 预期是 0ms 实际上 大于 1ms

有很多因素会导致setTimeout的回调函数执行比设定的预期值更久。

首先是浏览器之间的差异, 在浏览器中,setTimeout()/`setInterval()`[7] 的每调用一次定时器的最小间隔是4ms,这通常是由于函数嵌套导致(嵌套层级达到一定深度),或者是由于已经执行的setInterval的回调函数阻塞导致的。例如:

function cb() { f(); setTimeout(cb, 0); }
setTimeout(cb, 0);

setInterval(f, 0);

在Chrome 和 Firefox中, 定时器的第5次调用被阻塞了;在Safari是在第6次;Edge是在第3次。Gecko 从这个版本 version 56[8]开始对 setInterval() 开始采用这样的机制(setTimeout()已经实现,具体请参考以下内容)。

一直以来,不同浏览器中出现这种最小延迟的情况有所不同(例如Firefox) – 从其他地方调用了setInterval( ),或者在嵌套函数调用setTimeout( ) 时(嵌套级别达到特定深度时),都会出现超时延迟。

那么浏览器中实现0ms延时的定时器,这里就需要用 window.postMessage ,这个并不在本次内容介绍中说明.

小结

这篇文章到这里就结束了,水平有限难免有纰漏,欢迎纠错。最后希望帮忙点点赞,这对我创作是无比的肯定和动力。希望可以帮到你

文章参考

www.paulirish.com/2011/reques…[9]
hacks.mozilla.org/2011/08/ani…[10]
developer.mozilla.org/zh-CN/docs/…[11]

本文转自 https://juejin.cn/post/7078941440989986829,如有侵权,请联系删除。

参考资料

[1]

https://developer.mozilla.org/zh-CN/docs/Web/API/setTimeout: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FsetTimeout

[2]

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/requestAnimationFrame: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FWindow%2FrequestAnimationFrame

[3]

https://developer.mozilla.org/zh-CN/docs/Web/API/Window/cancelAnimationFrame: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FWindow%2FcancelAnimationFrame

[4]

https://developer.mozilla.org/zh-CN/docs/Web/API/clearTimeout: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FclearTimeout

[5]

https://developer.mozilla.org/zh-CN/docs/Web/API/setInterval: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FsetInterval

[6]

https://developer.mozilla.org/zh-CN/docs/Web/API/clearInterval: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FclearInterval

[7]

https://developer.mozilla.org/zh-CN/docs/Web/API/setInterval: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FsetInterval

[8]

https://developer.mozilla.org/en-US/docs/Mozilla/Firefox/Releases/56: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fen-US%2Fdocs%2FMozilla%2FFirefox%2FReleases%2F56

[9]

https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/: https://link.juejin.cn/?target=https%3A%2F%2Fwww.paulirish.com%2F2011%2Frequestanimationframe-for-smart-animating%2F

[10]

https://hacks.mozilla.org/2011/08/animating-with-javascript-from-setinterval-to-requestanimationframe/: https://link.juejin.cn/?target=https%3A%2F%2Fhacks.mozilla.org%2F2011%2F08%2Fanimating-with-javascript-from-setinterval-to-requestanimationframe%2F

[11]

https://developer.mozilla.org/zh-CN/docs/Web/API/setTimeout#%E5%AE%9E%E9%99%85%E5%BB%B6%E6%97%B6%E6%AF%94%E8%AE%BE%E5%AE%9A%E5%80%BC%E6%9B%B4%E4%B9%85%E7%9A%84%E5%8E%9F%E5%9B%A0%EF%BC%9A%E6%9C%80%E5%B0%8F%E5%BB%B6%E8%BF%9F%E6%97%B6%E9%97%B4: https://link.juejin.cn/?target=https%3A%2F%2Fdeveloper.mozilla.org%2Fzh-CN%2Fdocs%2FWeb%2FAPI%2FsetTimeout%23%25E5%25AE%259E%25E9%2599%2585%25E5%25BB%25B6%25E6%2597%25B6%25E6%25AF%2594%25E8%25AE%25BE%25E5%25AE%259A%25E5%2580%25BC%25E6%259B%25B4%25E4%25B9%2585%25E7%259A%2584%25E5%258E%259F%25E5%259B%25A0%25EF%25BC%259A%25E6%259C%2580%25E5%25B0%258F%25E5%25BB%25B6%25E8%25BF%259F%25E6%2597%25B6%25E9%2597%25B4


版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/20480.html

(0)
小半的头像小半

相关推荐

发表回复

登录后才能评论
极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!