【问题标题】:Utilizing rxjs repeatWhen in http request pipe in order to repeat the request if desired response is not returned如果未返回所需的响应,则在 http 请求管道中使用 rxjs repeatWhen 以重复请求
【发布时间】:2021-03-18 17:37:07
【问题描述】:

我正在尝试使用我的 http 请求管道的以下简化版本来确保如果我的响应在 res.myCondition 中没有所需的数据来使用 repeatWhen 并进行另一个调用,但我显然没有使用 repeatWhen本来的样子。 (角度 8/rxjs 6.5)

意图是第一次调用进入地图,在那里我检查返回的数据,如果数据在那里,我会将它返回给我的组件中的订阅者,但如果我的资源中缺少 myCondition 我会喜欢重复 api 调用预先确定的次数,存储在 reties 中。

对我的 repeatWhen 实施有什么问题吗?

方法1:

return this.http.get()
   .pipe(map(res => res.myCondition ? res : null),
        repeatWhen(res => retries-- > 0 ? of(res) : res), 
        catchError((error: HttpErrorResponse) => (error))

【问题讨论】:

  • 我已经更新了我的答案,因为我在第一次尝试中做了一些错误的假设:-)

标签: angular rxjs rxjs-observables rxjs-pipeable-operators


【解决方案1】:

让我们分解一下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

【讨论】:

  • @kruschild 非常感谢您的回复!它有效,这是一个很好的解释!如果您不介意,请将 empty() 更新为 EMPTY,因为从 rxjs 6+ 起,empty() 已被弃用。我注意到 repeatWhen 是第一个被击中的东西,这是出乎意料的。关于它为什么这样做的任何想法?
  • 谢谢@Farnoosh,不知道它已被弃用。我更新了我的答案。总是乐于提供帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多