如何实现持续请求接口直至目标项出现的重试脚本?
解决持续轮询接口直至找到目标物品的问题
Hey Nick, 我来帮你捋清楚这个问题!你的思路方向是对的——用async/await配合循环来实现轮询比递归更靠谱,先给你指出现有代码里的几个小问题,再给你修正后的完整实现。
现有代码的问题
- 语法错误:你的
search函数缺少闭合的大括号,而且在Promise构造函数内部直接调用promise.then()是不合理的,这部分逻辑应该放在函数外部或者调用阶段处理。 - Promise构造函数的误用:
getProducts作为异步请求的调用,需要确保回调逻辑能正确触发resolve/reject;另外你可以简化数组过滤的逻辑,不用先push再判断长度,直接用find方法更高效。
修正后的实现方案
我们可以用迭代式的while循环来实现持续轮询,这比递归更安全(不会因为轮询次数过多导致调用栈溢出)。下面是调整后的完整代码:
// 先修正search函数,让它返回一个规范的Promise const search = (color) => { return new Promise(function(resolve, reject) { // 假设api.getItems是异步请求,第二个参数是请求完成后的回调 api.getItems("hats", (products) => { // 直接找到第一个匹配目标颜色的商品 const targetItem = products.find(p => p.color === color); targetItem ? resolve(targetItem) : reject("目标物品未找到"); }); }); }; // 轮询逻辑:持续尝试,失败后等待再重试 async function trySearch(color) { while (true) { try { console.log("正在轮询接口..."); const result = await search(color); console.log("找到目标物品:", result); return result; // 找到结果后终止循环并返回 } catch (err) { console.log(err, "500ms后重试..."); // 等待500ms再发起下一次请求,避免给服务器造成过大压力 await new Promise(resolve => setTimeout(resolve, 500)); } } } // 启动轮询,查找金色的帽子 trySearch('Gold');
为什么不用递归?
如果用递归实现,每次失败后调用trySearch自身,当轮询次数非常多的时候,会不断增加调用栈的深度,最终可能触发栈溢出错误。而while循环是迭代模式,每次循环都在同一个函数调用栈里执行,不会有这个风险,代码也更直观易读。
额外优化建议
- 添加最大重试次数:可以给
trySearch加一个参数,设置最大重试次数,避免无限轮询(比如服务器持续故障的情况)。 - 动态调整等待时间:比如失败几次后延长等待间隔,进一步降低服务器负载。
- 捕获请求异常:如果接口请求本身抛出网络错误等异常,也要确保能捕获到并进行重试。
举个带最大重试次数的优化例子:
async function trySearch(color, maxRetries = 100) { let retryCount = 0; while (retryCount < maxRetries) { try { console.log(`第${retryCount+1}次轮询接口...`); const result = await search(color); console.log("找到目标物品:", result); return result; } catch (err) { retryCount++; const waitTime = 500 * retryCount; // 每次失败后等待时间翻倍 console.log(err, `${waitTime}ms后重试...`); await new Promise(resolve => setTimeout(resolve, waitTime)); } } throw new Error(`超过最大重试次数(${maxRetries}),未找到目标物品`); }
内容的提问来源于stack exchange,提问作者NIck Perez
相关产品推荐
相关产品推荐

