Node.js中如何在列表尚有元素时重复执行API调用函数
解决方案:处理API频率限制并循环直到列表为空
先明确核心优化方向:放弃遍历1到10000的低效逻辑,直接处理目标ID列表;同时解决API频率限制问题,成功获取数据后移除对应ID,直到列表清空。
修改后的完整代码
let my_list = [1, 7, 9, 112, 15, 17, 19, 25]; // 你的初始ID列表 // 封装带重试机制的请求函数,处理429频率限制 const fetchBreweryWithRetry = async (id) => { try { const brewery = await findBreweriesById(id); return brewery; } catch (error) { // 针对429错误做重试处理 if (error.response?.status === 429) { // 优先用API返回的重试等待时间,默认60秒 const retryAfter = parseInt(error.response.headers.get('Retry-After')) || 60; console.log(`触发频率限制,等待${retryAfter}秒后重试ID ${id}`); await new Promise(resolve => setTimeout(resolve, retryAfter * 1000)); // 递归重试当前ID return fetchBreweryWithRetry(id); } // 其他错误直接抛出,也可根据需求自定义处理 throw error; } }; const processList = async () => { // 循环直到ID列表为空 while (my_list.length > 0) { // 复制当前列表的副本,避免遍历中修改原列表导致的遍历异常 const currentIds = [...my_list]; for (const id of currentIds) { // 主动控制请求频率:每分钟100次,即每600ms发起一次请求 await new Promise(resolve => setTimeout(resolve, 600)); try { const brewery = await fetchBreweryWithRetry(id); if (brewery) { console.log(brewery.brewery_name); // 成功获取数据后,从原列表移除该ID const index = my_list.indexOf(id); if (index !== -1) { my_list.splice(index, 1); } } else { console.log(`ID ${id} 未找到对应brewery`); // 如果不需要保留未找到结果的ID,可在这里同样执行移除操作 // const index = my_list.indexOf(id); // if (index !== -1) my_list.splice(index, 1); } } catch (error) { console.log(`处理ID ${id} 时出错:`, error.message); } } } console.log("所有元素处理完成!"); }; // 启动处理流程 processList();
关键逻辑说明
频率控制与重试
- 主动设置600ms间隔(对应每分钟100次请求),从根源减少触发429的概率
- 封装
fetchBreweryWithRetry函数,遇到429错误时,根据API返回的Retry-After头等待后自动重试,避免程序中断
循环与列表修改
- 用
while (my_list.length > 0)作为循环条件,确保直到所有ID处理完成才停止 - 每次循环开始时复制当前列表到
currentIds,避免遍历过程中修改原列表导致的元素跳过问题
- 用
元素移除时机
- 在成功获取到
brewery数据后,立即用splice从my_list中移除对应ID,保证下一轮循环不会重复处理已完成的ID
- 在成功获取到
额外优化建议
如果ID数量较多,推荐用Set代替数组存储ID,提升查找和移除的效率:
let my_ids = new Set([1, 7, 9, 112, 15, 17, 19, 25]); // 判断存在:my_ids.has(id) // 移除元素:my_ids.delete(id)
内容的提问来源于stack exchange,提问作者Tendekai Muchenje
相关产品推荐
相关产品推荐

