注:本系列ahooks源码分析基于v3.3.13。本人把源码抄了一份,主要是对源码做一些解读,详见[1]。今天我们来谈谈定时器。从useInterval和useTimeout的名字我们可以大致知道它们的作用对应于setInterval和setTimeout,那么相比后者有哪些优势呢?先看useInterval,代码简单,如下图:即时;constfnRef=useLatest(fn);useEffect(()=>{//忽略一些代码...//立即执行if(immediate){fnRef.current();}consttimer=setInterval(()=>{fnRef.current();},delay);//清除定时器return()=>{clearInterval(timer);};//动态修改delay,实现定时器间隔变化和暂停。},[delay]);}跟setInterval的区别如下:可以支持第三个参数,通过immediate可以让我们的timer立即执行。当改变延时时,旧的定时器会自动清零,同时启动一个新的定时器。通过useEffect的返回清零机制,开发者无需关注定时器的清零逻辑,避免内存泄露。这是很多开发者会忽略的一点。useTimeout和上面的很像,如下图,不做额外解释:useEffect(()=>{//...忽略部分代码consttimer=setTimeout(()=>{fnRef.current();},delay);return()=>{clearTimeout(timer);};//动态修改delay,实现Timer间隔变化和暂停。},[delay]);}setTimeout和setInterval的问题首先,setTimeout和setInterval是事件循环中宏任务的“两大主力”,而且他们的执行时间并不能像我们预期的那样准确。它需要等待前面任务的执行。比如下面的setTimeout的第二个参数设置为0,就不会立即执行。setTimeout(()=>{console.log('test');},0)另外还有一种情况,setTimeout和setInterval是在浏览器不可见时(比如最小化时)在不同的浏览器中设置的。它在不同的时间间隔表现不同。根据浏览器切换到其他标签页或最小化的时间,你的js定时器还准时吗?[2]这篇文章的实际结论如下:在谷歌浏览器中,当页面不可见时,setInterval的最小间隔会被限制为1s。Firefox的setInterval与Google的特性一致,但是IE浏览器并没有优化setInterval在不可见状态下的性能,不可见状态前后的间隔保持不变。在谷歌浏览器中,如果浏览器不可见时setTimeout的间隔小于1s,则变为1s,大于等于1s,则变为N+1s的间隔值。Firefox浏览器下setTimeout的最小间隔会变成1s,大于等于1s的间隔不变。ie浏览器处于不可见状态前后的间隔时间保持不变。这个结论我没有验证过,但是好像差别挺大的,另外提到一个选项,就是requestAnimationFrame。window.requestAnimationFrame()告诉浏览器——你要执行一个动画,要求浏览器在下次重绘前调用指定的回调函数来更新动画。该方法需要传入一个回调函数作为参数,在浏览器下一次重绘之前执行,以提高性能和电池寿命,所以在大多数浏览器中,当requestAnimationFrame()运行在后台选项卡或隐藏在一个里面时
