RxJS重试机制触发但未发起实际HTTP请求的问题咨询
问题根因
核心问题是shareReplay()操作符的放置位置错误,位于所有重试逻辑的上游,导致重试操作不会真正触发原始HTTP请求的重发。
RxJS中pipe内的操作符是从左到右依次封装的,下游操作符只会订阅它紧邻的上游操作符返回的Observable,你的代码执行逻辑如下:
- 操作符顺序:
http$->tap->map->shareReplay()->retryWhen->retry(4) shareReplay()会缓存上游Observable的最终状态(无论是成功返回的结果,还是抛出的错误),所有下游的订阅都会直接拿到缓存的结果/错误,不会重新触发上游的订阅- 当发生网络错误时,
shareReplay()已经缓存了这个错误状态,后续retryWhen、retry(4)重试的时候,只会从shareReplay()拿到缓存的错误,不会重新订阅最上游的http$,自然也就不会发起新的HTTP请求,只会触发你写在retryWhen里的打印日志。
另外你代码中delayWhen(() => timer(2000)缺少一个闭合的右括号,运行时会存在语法问题。
修复方案
把shareReplay()放到所有重试逻辑的下游即可,确保重试操作是直接作用在原始HTTP请求Observable上,重试成功后再共享结果:
const http$: Observable<Course[]> = this.http.request('/api/courses'); const courses$ = http$ .pipe( tap(() => console.log('HTTP request invoked ...')), map( res => res['payload'] ), retryWhen(errors => errors.pipe( tap(() => console.log('Error retry invoked ...')), delayWhen(() => timer(2000)) ) ), retry(4), shareReplay() // 移到重试逻辑之后 );
补充说明
你同时使用了retryWhen和retry(4),如果你的预期是请求失败后每隔2秒重试一次,累计重试4次就停止,当前写法逻辑是冗余的,可以直接把重试次数控制放到retryWhen里,避免逻辑混乱。
内容的提问来源于stack exchange,提问作者Mostafa Hamid
相关产品推荐
相关产品推荐

