Как лучше всего показать индикатор для запросов в полете, используя rxjs без побочных эффектов? - PullRequest
0 голосов
/ 30 мая 2018

Каков предпочтительный способ отображения индикатора загрузки для запроса в полете с использованием RXJS (и Angular2 +) без введения побочных эффектов в функцию pipe ()?

Вот варианты, которые я придумала,Есть ли каноническая рекомендация или лучший вариант?


Вариант 1: Используйте побочные эффекты через do ();

results$ = userEvent$.pipe(do(()=> { this.loading = true; }), switchMap(()=>  service.externalCall()), do(()=> { this.loading = false; }))

Плюсы: простейшие минусы: могут столкнуться с крайними случаями снесколько подписчиков, если не использовать «поделиться».


Вариант 2: Добавить отдельные подписки для установки индикатора загрузки

userEvent$.subscribe(()=> {this.loading = true;} )
const results$ = userEvent$.pipe(switchMap(()=>  service.externalCall()))
// Is this always guarenteed to fire after the first statement?
results$.subscribe(() => {this.loading = false;});

Плюсы: Нет побочных эффектов в операторе pipe ()

Минусы: больше наблюдаемых, плавающих вокруг Не ясно, если порядок является детерминированным.


Вариант 3: Создать новую тему

const subject = new Subject();
userEvent$.subscribe(()=> { this.loading = true; subject.next(); } )
const result$ = subject.asObservable().pipe(switchMap(() => service.externalCall()));
result$.subscribe(() => { this.loading = false; });

Плюсы: 100% детерминированность, нетпобочные эффекты

Минусы: приходится вводить еще одну тему

1 Ответ

0 голосов
/ 30 мая 2018

Лично я использую побочный эффект (do/tap), потому что он проще.

Вы можете использовать подход, при котором все сообщения моделируются как события.Таким образом, события, проходящие по одному каналу, могут быть «Загрузка», «Успех», «Сбой» и т. Д. Я видел этот подход специально с эффектами ngrx.Тогда вы просто фильтруете на основе того, что вы хотите.Вы должны поделиться, если у вас есть несколько подписок (что вы, вероятно, будете).Вот пример.

console.clear();
const { interval, of, throwError: _throw } = rxjs;
const { switchMap, take, delay, map, startWith, catchError, share } = rxjs.operators;

let callCount = 0;
function fakeApiCall() {
  callCount++;
  let response = callCount === 3
    ? _throw(new Error(callCount))
    : of(callCount);
  return response.pipe(delay(Math.random() * 1000));
}

const EventType = {
  Loading: 'Loading',
  Success: 'Success',
  Failure: 'Failure'
};

const trigger = interval(1000).pipe(take(5));

const stream = trigger.pipe(
  switchMap(() => {
    return fakeApiCall().pipe(
      map((x) => ({ type: EventType.Success, payload: x })),
      catchError((e) => of({ type: EventType.Failure, payload: e.message })),
      startWith({ type: EventType.Loading })
    );
  }),
  share()
);

const isLoading = stream.pipe(
  map((x) => x.type === EventType.Loading)
);

stream.subscribe(
  (x) => { console.log('stream', x); }
);

isLoading.subscribe(
  (x) => { console.log('isLoading', x); }
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.1.0/rxjs.umd.js"></script>

Или вы можете объединить триггер с результатом и отобразить каждый в состояние загрузки.Вы должны отключить звук и вернуть что-то из-за ошибки.

console.clear();
const { interval, merge, of, throwError: _throw } = rxjs;
const { delay, take, switchMap, share, catchError, mapTo, distinctUntilChanged } = rxjs.operators;

let callCount = 0;
function fakeApiCall() {
  callCount++;
  let response = callCount === 2
    ? _throw(new Error(callCount))
    : of(callCount);
  return response.pipe(delay(Math.random() * 1000));
}

const trigger = interval(1000).pipe(take(5));

const stream = trigger.pipe(
  switchMap(() => fakeApiCall().pipe(catchError((e) => of('err')))),
  share()
);

const isLoading = merge(
  trigger.pipe(mapTo(true)),
  stream.pipe(mapTo(false))
).pipe(
  distinctUntilChanged()
);

isLoading.subscribe(
  (x) => { console.log('isLoading', x); }
);

stream.subscribe(
  (x) => { console.log('stream next', x); }
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.1.0/rxjs.umd.js"></script>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...