rxjs错误处理>在catchError源上停止发出

时间:2019-06-24 20:28:42

标签: angular error-handling rxjs reactive-programming

rxjs catchError运算符让我有些困惑。这是一个使用Angular的简单示例:

(实时演示here

import { Component } from '@angular/core';
import { of, timer } from 'rxjs'
import { tap, catchError } from 'rxjs/operators'

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
})
export class AppComponent {
  constructor() {
    const source$ =  timer(1000, 1000).pipe(tap(n => {
      if (n === 3) {
        throw new Error('n === 3')
      }
    }))

    this.value$ = source$.pipe(catchError(err => {
      return of(42)
    }))
  }

  value$
}

{{ value$ | async }}

异步管道订阅的source$可观察值发出0,1,2,然后产生错误。这个错误被catchError运算符捕获,该运算符将错误地吞没并发出42。我想我知道。但是,发射随后停止了(我原以为是4,5,6,...)。有人可以解释为什么这种情况不会发生,以及是否有任何方法可以实现这种行为吗?

在下面这样的情况下,这对我来说很重要,在这种情况下,每次发出路线参数时我们都会加载新数据。假设我们导航到引发错误的路线(例如404、500等),我不希望事件流停止发出,因为那样我就无法导航回任何其他页面。我只想优雅地处理错误并继续关注路由更改。

this.foo$ = this._route.params.pipe(
  map(params => params.id),
  switchMap(id => this._fooServerClient.getOneById(id)),
  catchError(err => {
    return of(undefined)
  })
)

1 个答案:

答案 0 :(得分:2)

如果在Observable管道中发生异常,则是根据Observable的设计,相应的observable [引发错误]将处于错误状态,并且无法发出新的/进一步的值[即就像是退订]。

现在,为了保持您的外部可观察的生命[继续发出新值],然后以内部可观察的方式处理错误[即在内部可观察管道中使用catchError运算符,如下所示:

this.foo$ = this._route.params
                .pipe(
                      map(params => params.id),
                      switchMap(id => {
                          return this._fooServerClient.getOneById(id)
                                     .pipe(
                                      catchError(err => {
                                        return of(undefined);
                                      })
                                     )
                        }),

                );

内部可观察管道中有catchError将保持外部可观察生命[即即使内部可观察到抛出异常,也要继续发出新值。]