控制台偶发429状态码请求失败错误求助
解决OpenWeatherMap API返回429状态码的问题
首先咱们先把问题点透:429状态码就是「请求次数过多」,是OpenWeatherMap的API服务端在提醒你,你的调用频率或者总次数已经超过了它给你分配的配额限制,所以才会偶发出现请求挂起、超时,有时候又能正常加载的情况——毕竟限流是按时间窗口统计的,偶尔触达上限就会报错,没超的时候就正常。
结合你提供的代码片段(用了Promise和axios.all批量请求),给你几个针对性的解决办法:
1. 先确认你的API密钥配额
先去OpenWeatherMap的账号后台查一下你当前API密钥的限制:免费版一般是每分钟最多60次请求,每天最多1000次,如果你的业务调用量已经摸到这个上限,要么优化请求逻辑,要么考虑升级付费版。
2. 给批量请求加频率控制
你用了axios.all,会一次性把所有请求发出去,很容易在短时间内触发每分钟的请求限制。改成顺序请求+固定间隔的方式,避免瞬间打满配额:
// 定义一个延迟函数 const delay = (ms) => new Promise(resolve => setTimeout(resolve, ms)); // 批量请求改为顺序执行,每次间隔1秒(适配免费版60次/分钟的限制) const sequentialRequests = async (requests) => { const results = []; for (const req of requests) { results.push(await req); await delay(1000); } return results; }; // 替换原来的axios.all调用 let getWeather = new Promise(function(resolve, reject) { getCity.then(apiData => { // 把你的axios请求数组放这里 const weatherRequests = [ axios.get('...'), axios.get('...') ]; sequentialRequests(weatherRequests) .then(resolve) .catch(reject); }); });
3. 给429错误加智能重试逻辑
偶发的429可以通过重试解决,但不能无脑重试——用指数退避策略(每次重试的间隔翻倍),避免再次触发限流:
// 带指数退避重试的请求函数 const fetchWithRetry = async (axiosConfig, retries = 3, delayMs = 1000) => { try { return await axios(axiosConfig); } catch (error) { // 只有429错误且还有重试次数时才重试 if (error.response?.status === 429 && retries > 0) { await new Promise(resolve => setTimeout(resolve, delayMs)); // 下次重试间隔翻倍 return fetchWithRetry(axiosConfig, retries - 1, delayMs * 2); } // 其他错误或者重试耗尽,直接抛出 throw error; } }; // 在你的请求中使用这个函数 let getWeather = new Promise(function(resolve, reject) { getCity.then(apiData => { axios.all([ fetchWithRetry({ url: '...', method: 'get' }), fetchWithRetry({ url: '...', method: 'get' }) ]) .then(resolve) .catch(reject); }); });
4. 缓存请求结果,减少重复调用
天气数据更新频率不高,把已经获取的结果缓存起来(比如用localStorage或者内存缓存),相同城市的请求直接用缓存,不用每次都调用API:
// 从缓存获取天气数据(有效期10分钟) const getCachedWeather = (cityId) => { const cached = localStorage.getItem(`weather_${cityId}`); if (cached) { const { data, timestamp } = JSON.parse(cached); if (Date.now() - timestamp < 10 * 60 * 1000) { return Promise.resolve(data); } } return null; }; // 保存天气数据到缓存 const saveWeatherToCache = (cityId, data) => { localStorage.setItem(`weather_${cityId}`, JSON.stringify({ data, timestamp: Date.now() })); }; // 修改你的getWeather逻辑,加入缓存判断 let getWeather = new Promise(function(resolve, reject) { getCity.then(apiData => { const cityId = apiData.id; // 假设apiData里有城市唯一标识 getCachedWeather(cityId) .then(cachedData => { if (cachedData) { resolve(cachedData); return; } // 没有缓存才发起API请求 axios.all([/* 你的请求数组 */]) .then(results => { saveWeatherToCache(cityId, results); resolve(results); }) .catch(reject); }) .catch(reject); }); });
最后还要排查一下你的页面逻辑:有没有重复调用getWeather的情况?比如组件重复挂载、用户频繁触发请求按钮,这些都会额外消耗你的请求配额。
内容的提问来源于stack exchange,提问作者user3442612
相关产品推荐
相关产品推荐

