react接口防抖处理

发布于:2025-08-09 ⋅ 阅读:(19) ⋅ 点赞:(0)

防抖(Debounce)概念

防抖是一种优化技术,用于限制函数的执行频率。当一个函数被频繁调用时(比如用户输入、窗口大小调整等),防抖可以确保函数只在最后一次调用后的一段时间内执行一次,避免不必要的重复执行。

生活中的例子

想象你在电梯门前,当有人要进入电梯时,电梯门会延迟关闭,如果在这期间又有人要进来,电梯门会重新开始延迟计时。只有当一段时间内没有人再进来时,电梯门才会真正关闭。这就是防抖的原理。

代码详解

import { useCallback, useRef } from 'react';

/**
 * 防抖Hook - 用于延迟执行函数调用,避免函数被频繁触发
 * 
 * 防抖原理:当函数被触发时,设置一个延迟定时器,如果在延迟时间内函数再次被触发,
 * 则清除之前的定时器并重新设置,直到延迟时间到达后才真正执行函数
 * 
 * @param {Function} callback - 需要防抖的回调函数
 * @param {number} delay - 防抖延迟时间(毫秒)
 * @returns {Function} - 防抖后的函数
 * 
 * @example
 * // 创建一个防抖搜索函数,延迟500ms执行
 * const debouncedSearch = useDebounce(async (query) => {
 *   const result = await searchAPI(query);
 *   return result;
 * }, 500);
 * 
 * // 使用防抖函数
 * const handleSearch = async (value) => {
 *   try {
 *     // 只有在用户停止输入500ms后才会真正调用searchAPI
 *     const result = await debouncedSearch(value);
 *     console.log(result);
 *   } catch (error) {
 *     console.error(error);
 *   }
 * };
 * 
 * // 应用场景:
 * // 1. 搜索框输入实时搜索(避免每次输入都发送请求)
 * // 2. 窗口大小调整事件处理
 * // 3. 按钮点击防止重复提交
 * // 4. 表单验证(避免每次输入都进行验证)
 */
export const useDebounce = (callback, delay) => {
  // 使用useRef保存定时器引用,确保在多次渲染间保持同一引用
  // 这样可以在每次调用时清除之前的定时器
  const timeoutRef = useRef(null);
  
  // 使用useCallback缓存返回的函数,避免不必要的重新创建
  // 依赖项为callback和delay,当它们变化时才重新创建函数
  return useCallback((...args) => {
    // 清除之前的定时器,防止函数执行
    // 这是防抖的关键步骤,确保只有最后一次调用会生效
    if (timeoutRef.current) {
      clearTimeout(timeoutRef.current);
    }
    
    // 返回Promise以支持异步操作
    // 这样调用方可以使用async/await处理异步结果
    return new Promise((resolve, reject) => {
      // 设置新的定时器,在延迟时间到达后执行回调函数
      timeoutRef.current = setTimeout(async () => {
        try {
          // 执行传入的回调函数,并传入所有参数
          // 使用async/await支持异步回调函数
          const result = await callback(...args);
          
          // 成功执行后,通过resolve返回结果
          resolve(result);
        } catch (error) {
          // 如果回调函数执行出错,通过reject抛出错误
          reject(error);
        }
      }, delay);
    });
  }, [callback, delay]);
};

export default useDebounce;

1. Hook 签名和文档

export const useDebounce = (callback, delay) => {

这个 Hook 接收两个参数:

  •  callback : 需要防抖的函数
  •  delay : 延迟时间(毫秒)

2. 定时器引用

const timeoutRef = useRef(null);

使用  useRef  保存定时器引用,确保在多次渲染之间保持对同一个定时器的引用。这是防抖实现的关键,因为我们需要能够清除之前的定时器。

3. 缓存返回函数

return useCallback((...args) => {
  // 函数实现
}, [callback, delay]);

使用  useCallback  缓存返回的函数,避免在每次重新渲染时创建新函数。只有当  callback  或  delay  变化时才会重新创建。

4. 防抖核心逻辑

// 清除之前的定时器
if (timeoutRef.current) {
  clearTimeout(timeoutRef.current);
}

// 设置新的定时器
timeoutRef.current = setTimeout(async () => {
  const result = await callback(...args);
  resolve(result);
}, delay);

这部分是防抖的核心实现:

  1. 每次函数被调用时,首先清除之前的定时器
  2. 然后设置一个新的定时器,在延迟时间后执行回调函数
  3. 如果在延迟时间内函数再次被调用,会重新执行第1步和第2步

5. Promise 支持

return new Promise((resolve, reject) => {
  timeoutRef.current = setTimeout(async () => {
    try {
      const result = await callback(...args);
      resolve(result);
    } catch (error) {
      reject(error);
    }
  }, delay);
});

通过返回 Promise,这个 Hook 支持异步回调函数,调用方可以使用 async/await 处理异步结果。

实际使用场景

1. 搜索框输入防抖

const debouncedSearch = useDebounce(async (query) => {
  const result = await searchAPI(query);
  return result;
}, 500);

const handleSearch = async (value) => {
  try {
    // 用户快速输入时,只会发送最后一次请求
    const result = await debouncedSearch(value);
    setSearchResults(result);
  } catch (error) {
    console.error('搜索失败:', error);
  }
};

2. 窗口大小调整

const debouncedResize = useDebounce((size) => {
  // 处理窗口大小调整逻辑
  updateLayout(size);
}, 300);

useEffect(() => {
  const handleResize = () => {
    debouncedResize({ width: window.innerWidth, height: window.innerHeight });
  };
  
  window.addEventListener('resize', handleResize);
  return () => window.removeEventListener('resize', handleResize);
}, [debouncedResize]);

工作流程图解

用户输入:  a ------------------ ab ------------------- abc ------>
          ↑                     ↑                      ↑
        调用1                 调用2                  调用3
          |                     |                      |
      清除定时器             清除定时器              清除定时器
          |                     |                      |
      设置定时器T1          设置定时器T2           设置定时器T3
          |                     |                      |
      T1被清除              T2被清除               T3执行回调
          |                     |                      |
          +---------------------+----------------------↓
                                                执行一次回调函数

优势

  1. 性能优化:减少不必要的函数调用,降低系统负载
  2. 用户体验:避免频繁的网络请求或界面更新
  3. 灵活性:支持同步和异步回调函数
  4. 易用性:封装成 Hook,使用简单方便

这个防抖 Hook 是一个非常实用的工具,可以有效提升应用的性能和用户体验。


网站公告

今日签到

点亮在社区的每一天
去签到