Лично я использую побочный эффект (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>