如何使用Axios按顺序拉取远程对象数组关联数据解决429错误?
问题场景
持有一组Yelp商家的ID列表,希望通过Axios逐个拉取每个ID对应的商家关联数据。尝试编写如下逻辑实现拉取功能,但始终触发Axios返回的429(请求过多)错误,报错信息为:[Unhandled promise rejection: Error: Request failed with status code 429]
已尝试过这段代码的多种改写形式,但问题始终存在,现有代码如下:
export const _fetchBusinessesDetails = async (ids : any[]) => { const businesses : Array<string> = []; const headers = { Authorization: 'Bearer <token>', 'Content-Type': 'application/json', }; ids.map(async (id : string) => { const res = await axios.get(`https://api.yelp.com/v3/businesses/${id}`, { headers }); console.log(res.data || res.response.data.message); if (res.data) { businesses.push(res.data); } console.log(res.response.data.message); }); return businesses; };
问题根因
- 核心错误是
Array.map搭配async回调的写法完全达不到“逐个拉取”的效果:map遍历数组是同步执行的,会在毫秒级时间内触发所有async回调,相当于同一瞬间向Yelp接口发送所有ID对应的请求,瞬间打满接口限流阈值,必然返回429错误。 - 缺少异步流程控制:外层的async函数不会等待map内部返回的Promise完成,会直接返回初始的空数组,根本拿不到拉取到的商家数据。
- 缺少错误捕获逻辑:触发429错误时没有对应的catch块处理,异常直接抛出为未捕获的Promise rejection。
- 代码存在逻辑bug:正常请求成功的流程中不存在
res.response对象,直接读取该属性会触发空引用错误,中断执行流程。
修正实现
实现严格串行拉取、内置请求间隔与429自动重试的可运行代码:
export const _fetchBusinessesDetails = async (ids: string[]) => { const businesses: any[] = []; const headers = { Authorization: 'Bearer <token>', 'Content-Type': 'application/json', }; // 用for...of循环替代map,逐次等待上一个请求完成后再发送下一个 for (const id of ids) { try { const res = await axios.get(`https://api.yelp.com/v3/businesses/${id}`, { headers }); if (res.data) { businesses.push(res.data); } // 每次请求完成后留300ms间隔,匹配Yelp接口的限流要求 await new Promise(resolve => setTimeout(resolve, 300)); } catch (err: any) { // 捕获429限流错误,等待1秒后重试当前请求 if (err.response?.status === 429) { await new Promise(resolve => setTimeout(resolve, 1000)); const retryRes = await axios.get(`https://api.yelp.com/v3/businesses/${id}`, { headers }); if (retryRes.data) businesses.push(retryRes.data); continue; } // 其他错误直接打印日志跳过,不中断整体拉取流程 console.log(`拉取商家${id}失败:`, err.response?.data?.message || err.message); } } return businesses; };
注意事项
Yelp公开接口的默认限流标准为每分钟最多500次请求,换算到每秒不到9次请求,瞬间并发发送大量请求一定会触发429错误。
不要直接用Promise.all批量提交所有请求,哪怕要做适度并发优化,也必须搭配请求间隔、限流控制和错误捕获逻辑,否则容易被接口封禁访问权限。
内容的提问来源于stack exchange,提问作者Ali H. Kudeir
相关产品推荐
相关产品推荐

