Есть ли оператор канала, который будет выполнять код до разрешения подписки? пример: http вызов - PullRequest
1 голос
/ 15 апреля 2020

Я делаю HTTP-вызовы и хочу установить индикатор загрузки до выполнения HTTP-вызова. На данный момент я делаю:

this.loadingIndicatorService.setLoadingIndicatorOn(true)
    this.cop.getunMappedTechnologyDetails().pipe(
      finalize(() => {
        this.loadingIndicatorService.setLoadingIndicatorOn(false);
      }),
    ).subscribe(
      res => {...}

Но я бы хотел установить индикатор загрузки внутри трубы, если это возможно, чтобы я мог быть уверен, что он работает, и чтобы я мог легко скопировать / вставить его в перед всеми моими подписками. (Я посмотрел на AOP, но в данном конкретном случае это кажется непрактичным)

нажатие не работает, потому что сначала выполняется выборка, а затем воздействие на результат, но я показываю его как визуальный для того, что я хочу получить:

this.cop.getunMappedTechnologyDetails().pipe(
      tap(() => this.loadingIndicatorService.setLoadingIndicatorOn(true)),
      finalize(() => {
        this.loadingIndicatorService.setLoadingIndicatorOn(false);
      }),
    ).subscribe(
      res => {...}

Возможно, я тоже искал обобщенную функцию c, но сейчас мне нужно быстрое решение, где я мог бы вставить эти каналы перед моими подписками.

РЕДАКТИРОВАТЬ: я пробовал вариант Jan-Niklas Wortmann с defer, но я получаю сообщение об ошибке .pipe:

Затем я попытался использовать его внутри трубы:

this.cop.getunMappedSafeDetails().pipe(
      defer(() => {
        this.loadingIndicatorService.setLoadingIndicatorOn(true);
        return this.cop.getunMappedSafeDetails();
      }),
      finalize(() => {
        this.loadingIndicatorService.setLoadingIndicatorOn(false);
      }),
    ).subscribe(...);

Но у меня ошибка:

Argument of type 'Observable<String[]>' is not assignable to parameter of type 'OperatorFunction<String[], {}>'.
  Type 'Observable<String[]>' provides no match for the signature '(source: Observable<String[]>): Observable<{}>'.

Ответы [ 2 ]

0 голосов
/ 15 апреля 2020

Напишите так:

this.cop.getunMappedTechnologyDetails().pipe(
  startWithTap(() => this.loadingIndicatorService.setLoadingIndicatorOn(true)),
  finalize(() => this.loadingIndicatorService.setLoadingIndicatorOn(false)),
)

Всякий раз, когда вы подписываетесь на вышеприведенную Наблюдаемую, startWithTap выполнит все, что вы передадите мгновенно, а затем переключится на Исходную наблюдаемую. Наконец, finalize выполнит обратный вызов, когда исходный Observable завершится.

И пользовательский оператор для него:

import { Observable, of } from 'rxjs';
import { switchMap, tap } from 'rxjs/operators';

export function startWithTap<T>(callback: () => void) {
  return (source: Observable<T>) =>
    of({}).pipe(tap(callback), switchMap((o) => source));
}
0 голосов
/ 15 апреля 2020

вы можете использовать defer для этой цели.

Код будет выглядеть следующим образом:

defer(() => {
   this.loadingIndicatorService.setLoadingIndicatorOn(true));
   return this.cop.getunMappedTechnologyDetails();
}).pipe(finalize(() => {
        this.loadingIndicatorService.setLoadingIndicatorOn(false);
  }),
).subscribe(
  res => {...}
)

defer - это побочный эффект, который возникает, когда вы подписываетесь на это наблюдаемое, поэтому это своего рода противоположность finalize. Но обратите внимание, это выполняется каждый раз, когда вы подписываетесь на наблюдаемый

...