注:本系列对 ahooks 的源码解析是基于 v3.3.13。自己 folk 了一份源码,主要是对源码做了一些解读,可见 详情[1]。,今天我们来聊聊定时器。,看名称,我们就能大概知道,它们的功能对应的是 setInterval 和 setTimeout,那对比后者有什么优势?,先看 useInterval,代码简单,如下所示:,跟 setInterval 的区别如下:,useTimeout 跟上面很类似,如下所示,不再做额外解释:,首先,setTimeout 和 setInterval 作为事件循环中宏任务的“两大主力”,它的执行时机不能跟我们预期一样准确的,它需要等待前面任务的执行。比如下面的 setTimeout 的第二个参数设置为 0,并不会立即执行。,另外还有一种情况,setTimeout 和 setInterval 在浏览器不可见的时候(比如最小化的时候),不同的浏览器中设置不同的时间间隔的时候,其表现不一样。根据 当浏览器切换到其他标签页或者最小化时,你的js定时器还准时吗?[2] 这篇文章的实践结论如下:,这个结论,我没有验证过,但看起来差异挺大,其中还提到了另外一个选择,就是 requestAnimationFrame。,window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行,为了提高性能和电池寿命,因此在大多数浏览器里,当requestAnimationFrame() 运行在后台标签页或者隐藏的 <iframe> 里时,requestAnimationFrame() 会被暂停调用以提升性能和电池寿命。,所以,ahooks 也提供了使用 requestAnimationFrame 进行模拟定时器处理的 hook,我们一起来看下。,直接看 useRafInterval。(useRafTimeout 和 useRafInterval 类似,这里不展开细说)。,可以看到,跟前面的 useInterval 大部分代码逻辑都是一样的,只是定时使用了 setRafInterval 方法,清除定时器用了 clearRafInterval。,直接上代码:,首先是用 typeof 判断进行兼容逻辑处理,假如不兼容,则兜底使用 setInterval。,初始记录一个 start 的时间。,在 requestAnimationFrame 回调中,判断现在的时间减去开始时间有没有达到间隔,假如达到则执行我们的 callback 函数。更新开始时间。,清除定时器。,假如不支持 cancelAnimationFrame API,则通过 clearInterval 清除,支持则直接使用 cancelAnimationFrame 清除。,关于定时器,我们平时用得不少,但经常有同学容易忘记清除定时器,结合 useEffect 返回清除副作用函数这个特性,我们可以将这类逻辑一起封装到 hook 中,让开发者使用更加方便。,另外,假如希望在页面不可见的时候,不执行定时器,可以选择 useRafInterval 和 useRafTimeout,其内部是使用 requestAnimationFrame 进行实现。,[1]详情: https://github.com/GpingFeng/hooks。,[2]当浏览器切换到其他标签页或者最小化时,你的js定时器还准时吗?: https://juejin.cn/post/6899796711401586695#comment。
© 版权声明
文章版权归作者所有,未经允许请勿转载。