Обработка ошибок rxjs> на catchError источник перестает излучать - PullRequest
0 голосов
/ 24 июня 2019

Я немного сбит с толку оператором rxjs catchError. Вот простой пример использования Angular:

(живое демо здесь )

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 Ответ

2 голосов
/ 25 июня 2019

По замыслу 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 во внутреннем наблюдаемом конвейере будет поддерживать внешнее наблюдаемое в реальном времени [т.е. продолжать излучать новое значение, даже если внутреннее наблюдаемое выбрасывает исключение].

...