1. 本际云推荐 - 专业推荐VPS、服务器,IDC点评首页
  2. 云主机运维
  3. VPS运维

演示当定时器在页面最小化时无法执行

ahooks源码解析系列文章之定时器

本篇文章是ahooks源码解析系列文章的第七篇,主要总结以下几点:

演示当定时器在页面最小化时无法执行

  • 巩固React Hooks的理解。
  • 学习如何抽象自定义Hooks,构建属于自己的React Hooks工具库。
  • 培养阅读学习源码的习惯,工具库是一个对源码阅读不错的选择。

注:本系列对ahooks的源码解析是基于v3.3.13。我自己folk了一份源码,主要是对源码做了一些解读,可见详情。

使用useInterval和useTimeout替代setInterval和setTimeout

下面介绍两个Hooks,即useInterval和useTimeout。它们的功能对应的是setInterval和setTimeout,那它们有什么优势呢?

先看useInterval:

function useInterval(
  fn: ()=> void,
  delay: number | undefined,
  options?: {
    immediate?: boolean;
  },
){
  const immediate = options?.immediate;
  const fnRef = useLatest(fn);
  
  useEffect(() => {
    // 省略部分代码...
    
    // 立即执行
    if (immediate) {
      fnRef.current();
    }
    
    const timer = setInterval(() => {
      fnRef.current();
    }, delay);
    
    // 清除定时器
    return () => {
      clearInterval(timer);
    };
    
    // 动态修改 delay 以实现定时器间隔变化与暂停。
  }, [delay]);
}

其区别如下:

  • 可以支持第三个参数,通过immediate能够立即执行我们的定时器。这样就可以在变更delay的时候,会自动清除旧的定时器,并同时启动新的定时器。
  • 通过useEffect的返回清除机制,开发者不需要关注清除定时器的逻辑,避免内存泄露问题。

useTimeout跟useInterval很类似,这里不再赘述。主要需要注意的是,这两个Hooks代替了setInterval和setTimeout,具有更好的兼容性和更好的内存管理问题。在开发过程中,一定要记得及时清除定时器。

使用requestAnimationFrame替代setTimeout和setInterval

setTimeout和setInterval常常会出现一些问题,比如间隔时间不准确、在页面不可见的时候可能无法执行、不同浏览器之间差异大等问题。因此,为了解决这些问题,我们可以使用requestAnimationFrame。

window.requestAnimationFrame()告诉浏览器——你希望执行一个动画,并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数,该回调函数会在浏览器下一次重绘之前执行。为了提高性能和电池寿命,因此在大多数浏览器里,当requestAnimationFrame()运行在后台标签页或者隐藏的<iframe>里时,requestAnimationFrame()会被暂停调用以提升性能和电池寿命。

ahooks中也提供了使用requestAnimationFrame进行模拟定时器处理的hook,我们一起来看下:

useRafInterval和useRafTimeout

直接看useRafInterval。(useRafTimeout和useRafInterval类似,这里不展开细说):

function useRafInterval(
  fn: () => void,
  delay: number | undefined,
  options?: {
    immediate?: boolean;
  },
){
  const immediate = options?.immediate;
  const fnRef = useLatest(fn);
  
  useEffect(() => {
    // 省略部分代码...
    
    const timer = setRafInterval(() => {
      fnRef.current();
    }, delay);
    
    // 清除定时器
    return () => {
      clearRafInterval(timer);
    };
    
  }, [delay]);
}

上述代码中展示出,跟前面的useInterval大部分代码逻辑都是一样的,但不同的就是定时使用了setRafInterval方法,清除定时器用了clearRafInterval。

setRafInterval方法中,判断是否支持requestAnimationFrame,如果不支持则依旧使用setInterval。初始记录一个start的时间。在requestAnimationFrame回调中,判断现在的时间减去开始时间有没有达到间隔,假如达到则执行我们的callback函数。更新开始时间。

const setRafInterval = function (callback:()=>void, delay:number = 0):Handle{
if (typeof requestAnimationFrame === typeof undefined) {
// 如果不支持,还是使用 setInterval
return {
id: setInterval

原创文章,作者:小编小本本,如若转载,请注明出处:https://www.benjiyun.com/yunzhujiyunwei/vps-yunwei/7294.html