Angular 在http请求管道中使用rxjs repeatWhen,以便在未返回所需响应时重复请求
我正在尝试使用下面简化的http请求管道版本,以确保如果我的响应在res.myCondition中没有所需的数据,则可以使用repeatWhen并进行另一次调用,但我显然没有按预期的方式使用repeatWhen。(角度8/rxjs 6.5) 目的是让第一个调用进入映射,在映射中我检查返回的数据,如果数据在那里,我将在我的组件中将其返回给订阅者,但是如果res中缺少myCondition,我希望在reties中重复api调用预定的次数 关于我的repeatWhen实现哪里出了问题,有什么想法吗 方法1:Angular 在http请求管道中使用rxjs repeatWhen,以便在未返回所需响应时重复请求,angular,rxjs,rxjs-observables,rxjs-pipeable-operators,Angular,Rxjs,Rxjs Observables,Rxjs Pipeable Operators,我正在尝试使用下面简化的http请求管道版本,以确保如果我的响应在res.myCondition中没有所需的数据,则可以使用repeatWhen并进行另一次调用,但我显然没有按预期的方式使用repeatWhen。(角度8/rxjs 6.5) 目的是让第一个调用进入映射,在映射中我检查返回的数据,如果数据在那里,我将在我的组件中将其返回给订阅者,但是如果res中缺少myCondition,我希望在reties中重复api调用预定的次数 关于我的repeatWhen实现哪里出了问题,有什么想法吗 方
return this.http.get()
.pipe(map(res => res.myCondition ? res : null),
repeatWhen(res => retries-- > 0 ? of(res) : res),
catchError((error: HttpErrorResponse) => (error))
让我们对操作员的描述进行分解: 返回使用 完全的例外。如果源可观测调用complete(1),则 方法将发送到从通知程序返回的可观察对象。如果 可观察调用完成或错误(2),则此方法将调用 子订阅已完成或有错误。否则,这种方法 将重新订阅可观察的源(3) (1):我可以假设源可观测的
this.http.get()
将在get请求完成后调用complete,对吗?因此,当操作员最终被通知/调用时,会重复
(2):如果您达到了允许的重试次数,那么您就不想再重试了,对吗?因此,您必须从repeatWhen
(3):否则,只需返回一个发出单个值的可观察对象,以指示您要重试(重新订阅)get请求
因此,您可能正在寻求以下改进(编辑:请参见下面的“为什么这个答案是错误的”):
(*)请注意,我还将map
操作符替换为mergeMap
,以防止流发出null
值。如果您的条件不满足,它将返回一个空的可观测值,以便不发出任何信息
编辑:
好吧,我错了。在rxjs游乐场中尝试上述代码后,我注意到,repeatWhen
操作符没有为源可观察到的每个值调用匿名函数。取而代之的是,anonymous函数只调用一次,它必须返回一个基于作为参数接收的可观察通知的可观察值:
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)
)
),
...
);
let finished=false;
返回这个.http.get()
.烟斗(
合并映射(res=>{
完成=重试--
烟斗(
takeWhile(()=>!完成)
)
),
...
);
奇怪的是,通知
主体对于源可观察到的每个发射(http.get
),除了未定义
)之外,不会发射任何东西它只提供了未定义的
。因此我们可以强制改变完成的
标志来控制repeatWhen
操作符。我在另一个问题中找到了这个解决方法,所以:我更新了我的答案,因为我在第一次尝试中做了一些错误的假设:-)@kruschild非常感谢您的回答!它有效,而且这是一个很好的解释!!!如果你不介意,请将empty()更新为empty,因为empty()是空的从rxjs 6+开始就被弃用了。我注意到repeatWhen是第一个被击中的东西,这是出乎意料的。关于它为什么会这样做有什么想法吗?谢谢@Farnoosh,我不知道它被弃用了。我更新了我的答案。总是很乐意帮助。
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)
)
),
...
);