Обертывание rxjs observable для выполнения чего-либо до и после (например, показать / скрыть экран загрузки)

#typescript #rxjs #rxjs6

#typescript #rxjs #rxjs6

Вопрос:

Я пытаюсь создать функцию, которая обертывает заданный Observable и добавляет к нему экран загрузки.
Функция function wrapWithLoadingScreen<T>(obs$: Observable<T>): Observable<T> должна работать как :

  1. показать экран загрузки.
  2. выполнить observable, полученный в качестве параметра
  3. скрыть экран загрузки после того, как все значения будут отправлены.

Моя первоначальная идея реализации была:

 function wrapWithLoadingScreen<T>(obs$: Observable<T>): Observable<T> {
  return of(null).pipe(
    tap(() => console.log("show loading screen")),
    switchMap(() => obs$),
    finalize(() => console.log("hide loading screen"))
  );
}
  

но когда я привязываю другие операторы к результату этой функции, после этих цепочек выполняется «скрыть экран загрузки» (а не после исходного наблюдаемого завершения).

Вот пример: https://stackblitz.com/edit/rxjs-wrapping-observable

результат в консоли выше

 show loading screen
im reducing
im reducing
reducing finished so loading screen should be hidden
the result is 6
hide loading screen
  

то, к чему я стремлюсь, должно быть

 show loading screen
im reducing
im reducing
hide loading screen
reducing finished so loading screen should be hidden
the result is 6
  

Ответ №1:

Это связано с тем, что finalize выполняется после демонтажа, см. Эту проблему на GitHub для получения дополнительной информации. Это означает, что даже если вы используете finalize в середине цепочки, даже до reduce и mergeMap , он будет выполняться последним во время процесса демонтажа.

Что касается альтернативного решения вашей проблемы, вы можете использовать tap примерно так:

 function wrapWithLoadingScreen<T>(obs$: Observable<T>): Observable<T> {
  return of(null).pipe(
    tap(() => console.log("show loading screen")),
    switchMap(() => obs$),
    tap(
      () => {},
      () => console.log("hide loading screen"),
      () => console.log("hide loading screen")
    ),
  );
}
  

Помимо next обратного вызова, вы можете предоставить error complete tap оператору обратные вызовы and . См. RxJS Tap Doc для получения дополнительной информации об ошибке и завершенных обратных вызовах.

Комментарии:

1. Не знал, что вы можете нажать onError и onComplete . Спасибо, работает отлично.