React Hooks实现API1每2秒调用1分钟,解决请求堆积问题
解决方案:避免API轮询时的请求堆积问题
你的核心问题是用setInterval固定间隔触发请求,导致前一次请求pending时仍会发起新请求,最终堆积。解决思路是让下一次请求在前一次请求完成后再延迟2秒发起,而不是固定时间触发。以下是修改后的完整实现:
关键改进点
- 用状态标记当前是否有请求在进行,防止重复发起
- 替换
setInterval为递归setTimeout,确保请求串行执行 - 统一处理请求成功/失败的状态重置,避免状态异常
- 用
useRef管理定时器ID,方便清理副作用
修改后的代码
import { useState, useEffect, useRef } from 'react'; const YourComponent = () => { const [isPolling, setIsPolling] = useState(false); const [isRequestPending, setIsRequestPending] = useState(false); const pollTimerRef = useRef(null); const startTimeRef = useRef(null); // 用ref保存开始时间,避免状态更新导致的重新渲染问题 // 核心API调用逻辑 const callAPI1 = () => { if (isRequestPending) return; // 已有请求在进行,直接返回 setIsRequestPending(true); fetch('你的API1地址') .then(res => res.json()) // 根据实际接口调整解析逻辑 .then(data => { const conditionMet = /* 替换为你的条件判断,比如data.status === 'completed' */; const isTimeout = Date.now() - startTimeRef.current > 60000; if (conditionMet || isTimeout) { setIsPolling(false); if (conditionMet) { // 满足条件时调用API2 fetch('你的API2地址') .then(res => res.json()) .then(api2Data => { // 处理API2返回结果 console.log('API2返回:', api2Data); }) .catch(err => console.error('API2调用失败:', err)); } } else { // 前一次请求完成后,延迟2秒发起下一次 pollTimerRef.current = setTimeout(() => { callAPI1(); }, 2000); } }) .catch(err => { console.error('API1调用失败:', err); // 请求失败后仍继续轮询(可根据需求调整为停止) pollTimerRef.current = setTimeout(() => { callAPI1(); }, 2000); }) .finally(() => { setIsRequestPending(false); // 请求完成后重置状态 }); }; // 初始请求 + 启动轮询 const makeFirstCallForAPI1 = () => { startTimeRef.current = Date.now(); callAPI1(); setIsPolling(true); }; // 点击事件处理 const onClick = () => { if (!isPolling && !isRequestPending) { makeFirstCallForAPI1(); } }; // 组件卸载时清理定时器 useEffect(() => { return () => { if (pollTimerRef.current) { clearTimeout(pollTimerRef.current); } }; }, []); return ( <button onClick={onClick} disabled={isPolling || isRequestPending}> {isPolling ? '轮询中...' : '开始轮询'} </button> ); }; export default YourComponent;
代码说明
状态与Ref管理:
isPolling:标记是否处于轮询状态,用于控制按钮禁用状态isRequestPending:标记当前是否有API1请求在进行,直接阻止重复请求pollTimerRef:保存定时器ID,确保组件卸载时能正确清理startTimeRef:用ref保存轮询开始时间,避免状态更新导致的重新渲染
轮询逻辑:
- 初始请求时记录开始时间,之后每次请求完成后,判断是否满足终止条件(超时或符合业务条件)
- 若未满足终止条件,延迟2秒后发起下一次请求,确保请求串行执行
- 请求失败时可选择继续轮询或停止,示例中选择继续
副作用清理:
- 在组件卸载时清理定时器,避免内存泄漏
内容的提问来源于stack exchange,提问作者HAAM
相关产品推荐
相关产品推荐

