我知道计时器已经成为很多人在日常任务中使用的功能已有一段时间了。在 JavaScript 世界中,计时器通常使用 setTimeout 或 setInterval 函数来实现,如果你这样做的话,坏消息是这不是一个好的做法,我将尝试解释原因。
在开始解释我的想法之前,我有一个问题要问你:你能用手表报错时间吗?
如果您的答案是肯定的,我很抱歉浪费了您的宝贵时间,因为这篇文章不属于您。
另一方面,如果您的答案是否定的,我将解释为什么使用 setTimeout 或 setInterval 就像使用损坏的手表来获取时间。
首先,让我们考虑以下代码片段
function test() { let i = 0; setTimeout(() => console.log("hello"), 0); while (i < 5) { console.log("number ", i); i += 1; } console.log("world");
如果您在浏览器控制台中运行此代码片段,您将得到以下结果
此行为是由于 setTimeout 将回调添加到浏览器队列中,以便在空闲时处理它 (没有任务要做) 换句话说,回调传递给 setTimeout 的优先级较低
现在,知道了这一点,我想您将很难使用 setTimeout 函数来实现计时器,因为您可以同时有 2 个甚至 10 个刻度(取决于您的浏览器的繁忙程度)。这对于调试来说将是一场噩梦,但是我们有更好的解决方案吗?
为了提供更好的实现计时器的方法,我们应该使用 requestAnimationFrame 函数,因为它告诉浏览器在下一次绘制之前执行回调(换句话说,在 UI 发生任何更改之前)
这里的区别非常微妙,所以最好通过代码来理解。让我们收回之前的代码片段并稍微调整一下以比较 setTimeout 和 requestAnimationFrame
function testWithAnimationFrame() { let i = 0; setTimeout(() => console.log("hello"), 0); requestAnimationFrame(() => console.log("tell me the next paint")); while (i < 5) { console.log("number ", i); i += 1; } console.log("world"); }
在此示例中,我们可以看到,在 Chrome 上运行时,setTimeout 在 requestAnimationFrame 之前运行(尽管在极少数情况下会发生相反的情况)
但是如果你在 Firefox 上运行它,这将是输出
这看起来可能令人困惑,但如果你稍微注意一下,你会发现执行过程中没有发生任何绘画,因此如何处理这种情况取决于浏览器。
现在,如果我们可以调整代码片段以使浏览器重新绘制页面,让我们看看会发生什么
function testWithAnimationFrame2() { let i = 0; setTimeout(() => console.log("hello"), 0); requestAnimationFrame(() => console.log("tell me the next paint")); while (i < 5) { console.log("number ", i); i += 1; document.body.style.backgroundColor = "red"; } console.log("world"); }
这是 Chrome 上的输出
这是 Firefox 中的输出
正如您在日志中看到的,当浏览器在 UI 中进行更改时,requestAnimationFrame 函数将始终优先于其他计划的回调。
因为在网络上,我们不断地执行重绘,requestAnimationFrame 是实现计时器的明显选择。
该函数仅接受回调作为参数。为了向回调提供上下文,它应该采用一个时间戳,指示基于页面初始渲染时间的前一帧结束的时间。
该函数将返回一个表示请求标识符的整数,如果您希望使用 cancelAnimationFrame 函数取消请求,这会很有用。
要实现秒表,有一些要求:
考虑到所有这些要求,以下代码片段将为您创建一个秒表
我知道这可能是一篇很长的文章,但相信您会喜欢它。无论如何,如果您有任何疑问或有任何建议,请随时联系我。
感谢您阅读本文,再见?
以上是您不需要设置超时的详细内容。更多信息请关注PHP中文网其他相关文章!