如何将RxJS中已废弃的retryWhen转换为retry操作符?
将废弃的retryWhen转换为retry操作符
核心逻辑转换说明
RxJS的retryWhen被废弃后,推荐使用带配置或回调的retry操作符。你的原代码逻辑包含有限次数重试+自定义退避延迟+重试耗尽后的错误处理,可以通过retry的回调/配置对象完全实现:
转换后的代码(推荐写法)
import { throwError, timer } from 'rxjs'; return src.pipe( retry({ count: maxRetry, // 对应原逻辑的最大重试次数 delay: (error, retryAttempt) => { // retryAttempt从1开始计数(第一次重试为attempt 1) const currentRetriesLeft = maxRetry - retryAttempt; // 保留原代码的退避时间计算逻辑 const backoffTime = delayMs + (maxRetry + currentRetriesLeft) + backoffMs; return timer(backoffTime); }, onRetry: (error, retryAttempt) => { // 可选:添加重试日志,便于调试 console.log(`第${retryAttempt}次重试,剩余次数:${maxRetry - retryAttempt}`); } }), // 重试耗尽后处理错误并终止流 catchError(error => { console.error(`retryWithBackoff exceeded url: ${url} max: ${maxRetry} ${error} ${error.status} ${error.statusText} ${error.url}`); return throwError(() => new Error(`network error ${error.statusText} ${url} ${maxRetry}`)); }) );
关键细节说明
- 消除外部变量副作用:原代码依赖外部
retries变量递减,容易引发订阅复用问题。新写法通过retryAttempt参数计算剩余重试次数,逻辑更安全。 - 退避延迟优化:用
timer(backoffTime)替代原代码的of(error).pipe(delay(backoffTime)),效果一致且符合RxJS最佳实践。 - 修正错误终止逻辑:原代码中返回
of(...)会导致retryWhen无限重试(错误流未抛出终止信号),转换后通过catchError在重试耗尽后抛出错误,正确终止流。 - 代码可读性提升:
retry的配置对象将重试次数、延迟逻辑、重试回调拆分,结构更清晰。
兼容原逻辑的备选写法(不推荐)
如果必须保留原代码中retries变量的逻辑(存在副作用风险),可以这样写:
import { throwError, timer } from 'rxjs'; return src.pipe( retry((error, retryAttempt) => { if (retries-- > 0) { const backoffTime = delayMs + (maxRetry + retries) + backoffMs; return timer(backoffTime); } console.error(`retryWithBackoff exceeded url: ${url} max: ${maxRetry} ${error} ${error.status} ${error.statusText} ${error.url}`); return throwError(() => new Error(`network error ${error.statusText} ${url} ${maxRetry}`)); }) );
注意:该写法依赖外部
retries变量,若Observable被多次订阅,会导致retries值被意外修改,引发难以排查的问题。
内容的提问来源于stack exchange,提问作者born2net
相关产品推荐
相关产品推荐

