订阅者不应因可观察的错误而停止

CSc*_*ulz 6 rxjs typescript

我正在为一个订阅者苦苦挣扎,它会在出错时自动取消订阅:

observable
  .subscribe(
    (data) => {
      // some logic encountering an error during execution
      // comparable to throw new Error()
    }
  )
Run Code Online (Sandbox Code Playgroud)

我可以通过使用 try / catch 来防止它:

observable
  .subscribe(
    (data) => try { 
        // some logic encountering an error during execution
        // comparable to throw new Error()
      } catch(e) {
      }
  )
Run Code Online (Sandbox Code Playgroud)

但这感觉像是一种解决方法。

我已经深入研究了 Subscriber 和 SafeSubscriber 的来源,它们会在出错时自动调用取消订阅:

  private __tryOrUnsub(fn: Function, value?: any): void {
    try {
      fn.call(this._context, value);
    } catch (err) {
      this.unsubscribe();
      throw err;
    }
  }
Run Code Online (Sandbox Code Playgroud)

实现自己的订阅者或使用 try/catch 是防止这种行为的唯一方法吗?

mar*_*tin 3

这是正确的行为。您可以使用该catch()运算符再次订阅同一源 Observable(或在出错时订阅不同的源 Observable)。

source
  .catch(err => Observable.of(null))
  .subscribe(...);
Run Code Online (Sandbox Code Playgroud)

这只会nullnext处理程序中返回,而不是原始错误。

另请注意,如果订阅者没有任何error处理程序,则任何异常都会重新引发。

例如,为了避免抛出错误,您可以这样做:

source
  ...
  .subscribe(..., error => {});
Run Code Online (Sandbox Code Playgroud)

然而,这总是会取消订阅链,因为这是 Observables 的基本原则之一。它们会发出零个或多个next通知以及一个completeerror多个通知,但绝不会同时发出两者。

很难说出您不想取消订阅的地方要解决什么问题,有时您可以使用Subject并仅传递next通知并忽略其余的...:

const subject = new Subject();
source.subscribe(val => subject.next(val));

subject.subscribe(...);
Run Code Online (Sandbox Code Playgroud)

  • @CSchulz 那是不可能的。 (4认同)
  • 我想优雅地处理订阅者中的错误而不丢失订阅。 (2认同)