Angular 无法理解如何处理错误并继续使用RXJS订阅

Angular 无法理解如何处理错误并继续使用RXJS订阅,angular,rxjs,Angular,Rxjs,我很难理解这个概念。我有两个表单可以由同一个xhr调用处理。因此,我通过公共流发送表单提交,并切换到xhr调用。我正试图使用catchError来处理任何500,这是有效的(调用.publish(error)会弹出一个包含错误消息的对话框),但随后订阅立即完成!我原以为这会不断地从search$流获取输入,直到我调用了this.search$.complete()(发生在componentDestroy上)。关于RXJS的“捕捉并继续聆听”,我遗漏了什么 this.search$.pipe(

我很难理解这个概念。我有两个表单可以由同一个xhr调用处理。因此,我通过公共流发送表单提交,并切换到xhr调用。我正试图使用catchError来处理任何500,这是有效的(调用.publish(error)会弹出一个包含错误消息的对话框),但随后订阅立即完成!我原以为这会不断地从search$流获取输入,直到我调用了
this.search$.complete()
(发生在componentDestroy上)。关于RXJS的“捕捉并继续聆听”,我遗漏了什么

  this.search$.pipe(
      tap(() => this.pending = true),
      switchMap(criteria => this._dealer.search(criteria)),
      catchError(ErrorNotifierService.catchResponseErrorAsObservable)
    ).subscribe(response => {
      this.pending = false;
      if (ErrorNotifierService.isCaughtError(response)) {
        this._error.publish(ErrorNotifierService.getErrorNotification(response.error));
      } else {
        this.dsSearchResults.data = response;
      }
    }, () => console.log('subscribe errored'), () => console.log('subscribe completed?'));

您需要将
catchError
移动到
switchMap
调用中,因为您想从切换的可观察对象中“隐藏”错误。只需将其嵌套即可:

此.search$.pipe(
点击(()=>this.pending=true),
switchMap(标准=>this.\u dealer.search(标准)
.pipe(catchError(ErrorNotifierService.catchResponseErrorAsObservable))
)
).认购(……);
代码的问题是,在您的情况下,
switchMap
将切换到发出错误的可观察对象,从而结束订阅。我们希望在切换到可观测之前,将此错误映射到发射,以便生成的流甚至从未看到错误


您可以找到一个可运行的在线代码示例和修复的示例。

Perfect。感谢您对原因的详细解释。我需要花点时间来理解它,但我更改了我的应用程序以匹配您的示例,它完全按照预期工作。基本上,switchMap所做的是每次它接收到一个值,它订阅内部可观测值并转发这些发射。如果新值出现时前一个内部订阅尚未完成,它将首先取消订阅。如果catchError位于此之外,则此内部订阅将出错,从而导致switchMap将其转发到外部订阅。一旦可观测到的错误,它就不能再发射了。通过将catchError移动到内部,只有内部的可观测对象不再发射,但外部的可观测对象仍然可以发射,从而允许整个流继续运行。