当前位置: 首页 > news >正文

react接口防抖处理

防抖(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 是一个非常实用的工具,可以有效提升应用的性能和用户体验。

http://www.dtcms.com/a/319424.html

相关文章:

  • [网格图DP]3363. 最多可收集的水果数目
  • 视频二维码如何助力博物馆打造智慧讲解体验
  • 数据库事务总结
  • 升级g++编译器
  • RK3568项目(十二)--linux驱动开发之基础通讯接口(上)
  • 时序数据库的功能与应用价值
  • RPC 解析
  • Renesas Electronics RZ/V2N 评估套件
  • 从密钥生成到功能限制:Electron 中 secure-electron-license-keys 的完整集成方案
  • Spring Cloud系列—LoadBalance负载均衡
  • 5分钟了解OpenCV
  • 用 Enigma Virtual Box 把 Qt 程序压成单文件 EXE——从编译、收集依赖到一键封包
  • 大数据spark、hasdoop 深度学习、机器学习算法的音乐平台用户情感分析系统设计与实现
  • 多线程 future.get()的线程阻塞是什么意思?
  • Spark Memory 内存设计的核心组件
  • 2025年主流开源音视频播放项目深度解析
  • 数据结构——B-树、B+树、B*树
  • flutter-使用AnimatedDefaultTextStyle实现文本动画
  • 状压DP-子集枚举技巧
  • MySQL UNION 操作符详细说明
  • 机器视觉系统工业相机的成像原理及如何选型
  • 数据结构-哈希表(散列表)
  • 进程控制:进程的创建、终止、阻塞、唤醒、切换等生命周期管理操作
  • 基于深度学习的调制信号分类识别算法的研究生学习之旅
  • C语言sprintf、strcmp、strcpy、strcat函数详解:字符串操作的核心工具
  • Modbus转Profinet网关与西门子PLC的互联配置案例:用于永宏品牌变频器的控制实现
  • 一个基于 epoll 实现的多路复用 TCP 服务器程序,相比 select 和 poll 具有更高的效率
  • 并发编程(三)线程模型和通信
  • 【AI算法承载】海思3516DV500+IMX664方案一体机芯,开放AI算法部署二次开发
  • 蓝桥杯----数码管、按键、定时器与中断