让我们分解一下repeatWhen运算符的描述:
返回一个镜像源 Observable 的 Observable
一个完整的例外。如果源 Observable 调用完成 (1),这
方法将发射到从通知器返回的 Observable。如果说
Observable 调用完成或错误(2),那么这个方法会调用
子订阅完成或出错。否则这个方法
将重新订阅源 Observable(3)。
(1):我可以假设源 observable this.http.get() 将在 get 请求完成后调用 complete,对吗?所以repeatWhen 操作符最终会被通知/调用。
(2):如果您达到了允许的重试次数,那么您就不想再重试了,对吧?所以你必须从repeatWhen中的匿名函数(通知器)返回一个空流(一个不发出任何东西的observable)。
(3):否则只返回一个发出单个值的 observable,表明您要重试(重新订阅)get 请求
所以您可能正在寻找的改进如下(编辑:请参阅下面为什么这个答案是错误的):
return this.http.get()
.pipe(
mergeMap(res => res.myCondition ? of(res) : EMPTY), // (*)
repeatWhen(() => retries-- > 0 ? of(true) : EMPTY),
catchError((error: HttpErrorResponse) => (error)
)
(*) 请注意,我还将您的map 运算符替换为mergeMap,以防止流发出null 值。如果你的条件不满足,它会返回一个空的 observable 来代替发射任何东西。
编辑:
好吧,我错了。在 rxjs 操场上尝试了上面的代码后,我注意到 repeatWhen 运算符没有为源 observable 发出的每个值调用匿名函数。相反,匿名函数仅在必须返回一个基于它作为参数接收的可观察通知的可观察对象时才被调用:
let finished = false;
return this.http.get()
.pipe(
mergeMap(res => {
finished = retries-- <= 0 || res.myCondition;
return finished ? of(res) : EMPTY;
}),
repeatWhen((notifications) =>
notifications.pipe(
takeWhile(() => !finished)
)
),
...
);
奇怪的是,notifications 主题除了undefined 之外没有发出任何东西。对于来自可观察源 (http.get) 的每个发射,它只为您提供 undefined。所以我们可以强制改变finished 标志来控制repeatWhen 操作符。我在关于 SO 的另一个问题中找到了这个解决方法:RxJS repeat depending on emitted value