API调用报错时如何实现两次重试?如何解决递归重试方案的UnhandledPromiseRejection报错
现有代码的问题
- 递归调用未绑定外层Promise:出错时递归调用
this.callAPI()返回的是独立的新Promise,没有将它的执行结果和外层Promise的resolve/reject关联,外层Promise完全感知不到递归调用的状态,递归调用抛出的错误没有对应捕获逻辑,就会触发未处理Promise拒绝的报错。 - 重试计数逻辑不合理:
RETRY_API是类的实例属性,如果同一实例同时发起多个API请求,多个请求会共用同一个计数变量,导致重试逻辑互相干扰完全混乱;且函数入参的retry没有被实际使用,计数逻辑和入参脱钩。 - 多个分支未触发Promise回调:httpCode非200、自定义业务逻辑的分支里,既没有调用
resolve也没有调用reject,会导致外层的Promise永远处于pending状态,await永远等不到执行结果。 - 冗余的async标识:
callAPI方法和回调函数里的async关键字没有实际作用,当前逻辑没有用到await调用,属于冗余代码。
优化后的实现方案
实现核心思路:重试次数通过函数参数传递,避免全局属性污染;递归调用时直接将内层Promise的结果透传给外层,保证错误可以被外层catch捕获;所有逻辑分支都有明确的Promise结束回调。
调用代码
try { // 传入允许的重试次数,重试1次总共调用2次,传1即可 await this.callAPI(request, 1); } catch (error) { console.log('error', error); }
核心重试逻辑实现
private callAPI(request: any, remainRetry: number): Promise<any> { return new Promise((resolve, reject) => { someService.postApiRequest('api/url', request, (err: any, httpCode: number, data) => { // 请求成功且状态码符合预期,直接返回结果 if (!err && httpCode === 200) { // 此处补充自定义业务逻辑 return resolve(data); } // 出错或状态码不符合预期,判断是否还有重试次数 if (remainRetry > 0) { // 还有重试次数,递归调用并将内层Promise结果透传给外层 // 可自行添加重试延迟逻辑,避免瞬时请求触发限流 return resolve(this.callAPI(request, remainRetry - 1)); } // 无剩余重试次数,返回最终错误 const finalError = err || new Error(`请求失败,状态码:${httpCode}`); return reject(finalError); }); }); }
可选优化点
- 增加重试延迟:失败后等待固定时长再发起重试,避免瞬时高频请求触发接口限流,示例如下:
if (remainRetry > 0) { setTimeout(() => { resolve(this.callAPI(request, remainRetry - 1)); }, 300); // 300ms后重试 return; } - 增加重试判断规则:仅对特定类型的错误执行重试,比如仅网络错误、5xx服务端错误重试,4xx参数错误等重试也无法解决的场景直接抛出错误,减少无效请求。
内容的提问来源于stack exchange,提问作者GoGo
相关产品推荐
相关产品推荐

