如何在React应用中降低Axios Get请求频率?解决409超限问题
请求第三方API触发409速率限制问题修复
问题说明
调用第三方API时因请求速度过快超出速率限制,返回409错误。目标是每5秒发起一次请求(API限制为每秒1次),但程序仍不间断请求。尝试用setInterval包裹请求函数设置4秒间隔,未解决问题。
错误截图:
当前代码:
import React, { useState, useEffect } from "react"; import ISS from "./ISS"; import axios from "axios"; function Map() { const [coordinates, setCoordinates] = useState(''); const [loading, setLoading] = useState(true); useEffect(() => { setInterval(() => { getCoordinates(); }, 4000) }, []) const getCoordinates = async () => { try { const res = await axios.get("https://api.wheretheiss.at/v1/satellites/25544") setCoordinates(res.data); setLoading(false) } catch(err) { console.log(err); } } return( <div className="relative w-[620px] h-[475px] map flex content-center justify-center"> {!loading && <ISS coordinates={coordinates} />} </div> ); } export default Map;
问题根源
- 未清理定时器:
useEffect中创建的setInterval没有在组件卸载时清除,若组件多次挂载,会生成多个定时器同时运行,请求频率翻倍触发速率限制。 - 请求可能重叠:
setInterval会按时触发请求,不等待上一次异步请求完成,若请求耗时超过间隔时间,会出现多个请求并行,超出API限制。 - 函数引用不稳定:
getCoordinates每次组件渲染都会重新创建,useEffect依赖数组为空,导致定时器捕获的是旧版本函数,可能引发预期外的重复调用。
修复方案
方案1:串行请求(推荐)
用setTimeout替代setInterval,确保上一次请求完成后再发起下一次,同时清理定时器避免内存泄漏。
import React, { useState, useEffect, useCallback } from "react"; import ISS from "./ISS"; import axios from "axios"; function Map() { const [coordinates, setCoordinates] = useState(''); const [loading, setLoading] = useState(true); const [timerId, setTimerId] = useState(null); // 用useCallback稳定函数引用 const getCoordinates = useCallback(async () => { try { const res = await axios.get("https://api.wheretheiss.at/v1/satellites/25544"); setCoordinates(res.data); setLoading(false); // 请求完成后5秒发起下一次请求 const id = setTimeout(getCoordinates, 5000); setTimerId(id); } catch(err) { console.log(err); // 出错后延迟5秒重试 const id = setTimeout(getCoordinates, 5000); setTimerId(id); } }, []); useEffect(() => { // 初始化请求 const id = setTimeout(getCoordinates, 0); setTimerId(id); // 组件卸载时清除定时器 return () => { if (timerId) clearTimeout(timerId); }; }, [getCoordinates, timerId]); return( <div className="relative w-[620px] h-[475px] map flex content-center justify-center"> {!loading && <ISS coordinates={coordinates} />} </div> ); } export default Map;
方案2:优化setInterval用法
若坚持使用setInterval,需添加定时器清理逻辑,并稳定函数引用:
import React, { useState, useEffect, useCallback } from "react"; import ISS from "./ISS"; import axios from "axios"; function Map() { const [coordinates, setCoordinates] = useState(''); const [loading, setLoading] = useState(true); // 用useCallback稳定函数引用 const getCoordinates = useCallback(async () => { try { const res = await axios.get("https://api.wheretheiss.at/v1/satellites/25544"); setCoordinates(res.data); setLoading(false); } catch(err) { console.log(err); } }, []); useEffect(() => { // 创建定时器,每5秒执行一次 const intervalId = setInterval(getCoordinates, 5000); // 组件卸载时清除定时器 return () => clearInterval(intervalId); }, [getCoordinates]); return( <div className="relative w-[620px] h-[475px] map flex content-center justify-center"> {!loading && <ISS coordinates={coordinates} />} </div> ); } export default Map;
关键修复点
- 清理定时器:组件卸载时清除定时器,避免无效请求和内存泄漏。
- 稳定函数引用:用
useCallback包裹请求函数,确保useEffect依赖正确,避免不必要的重新执行。 - 串行请求控制:
setTimeout方式保证请求按顺序执行,不会出现重叠,更适配API速率限制。
内容的提问来源于stack exchange,提问作者Philip Chen
相关产品推荐
相关产品推荐

