如何在特定场景下使用retryWhen并获取错误状态码?
解决方案
你的核心问题在于服务端retryWhen的实现里,最终抛出的错误对象没有正确传递到组件的错误回调中,同时重试逻辑的终止条件处理存在偏差。我们可以通过调整retryWhen的逻辑,确保完整的错误信息能传递到组件,同时保留重试和差异化错误处理的能力。
第一步:修正服务中的重试逻辑
原来的concat(Observable.throw(error))引用的是retryWhen函数的外层error参数,这会导致最终抛出的错误不是最后一次请求失败的真实错误对象。我们可以用scan操作符跟踪重试次数,当次数达到上限或遇到非501错误时,抛出原始错误。
修改后的服务代码:
return this.prepaidPaymentProxyService.performAirtimePrepaidPayment(request) .retryWhen(errors => { let retryCount = 0; return errors.pipe( scan((_, error) => { retryCount++; // 仅当状态码为501且重试次数未达上限时,继续重试 if (retryCount <= 5 && error.header.statuscode === '501') { console.log(`Retry attempt ${retryCount}`); return error; } // 超过次数或非501错误,抛出原始错误 throw error; }, null), delay(1000) // 每次重试间隔1秒 ); });
第二步:组件中正确处理错误对象
现在完整的错误对象能传递到组件的error回调里了,你可以直接提取statuscode,执行差异化处理:
buyPrepaidMobile(data) { this.loader.startLoading(); this.buyPrepaidMobileService.onBuyPrepaidMobile(data).subscribe( response => { this.buyPrepaidMobileService.handlebuyPrepaidMobileSuccess(response); this.activeStep = 3; this.progressIndicator.setStep(3); this.loader.stopLoading(); }, error => { this.loader.stopLoading(); const statusCode = error.header.statuscode; if (statusCode === '501') { console.log('Retried 5 times, ended with failure'); } // 传入状态码调用统一错误处理函数 this.buyPrepaidMobileService.handlebuyPrepaidMobileError(statusCode); this.activeStep = 3; this.progressIndicator.setStep(3); } ); }
这里调整了loader.stopLoading()的顺序,避免重复启动加载的问题,同时明确区分了501重试失败的日志和通用错误处理逻辑。
原实现的问题根源
原来的take(5).concat(Observable.throw(error))中,error是retryWhen函数的外层参数,并非每次错误流中的具体错误对象,这导致组件拿到的错误不是最后一次请求的真实错误,自然无法正确提取statuscode。而scan的方式可以在每次错误发生时判断是否重试,终止时抛出原始错误,保证了错误信息的完整性。
内容的提问来源于stack exchange,提问作者Vinod Bhavnani
相关产品推荐
相关产品推荐

