обработка ошибок эффектов ngrx
у меня есть очень простой вопрос относительно эффектов @ngrx: как игнорировать ошибку, которая происходит во время выполнения эффекта, чтобы она не влияла на выполнение будущего эффекта?
моя ситуация такова: у меня есть действие (логин) и эффект, слушающий это действие. Если внутри этого эффекта происходит ошибка, Я хочу ее игнорировать. Когда логин отправляется во второй раз после этой ошибки, эффект должен быть выполнен во второй раз.
моя первая попытка сделать это было:
@Effect()
login$ = this.actions$
.ofType('LOGIN')
.flatMap(async () => {
console.debug('LOGIN');
// throw an error
let x = [];x[0]();
})
.catch(err => {
console.error('Error at login', err);
return Observable.empty();
});
диспетчер входа в систему в первый раз бросает и ловит ошибку, как и ожидалось. Однако, если я отправлю логин во второй раз после этого, ничего не произойдет; эффект не выполняется.
поэтому я попробовал следующий:
.catch(err => {
return this.login$;
});
, но это приводит к бесконечному циклу... Знаете ли вы, как поймать ошибку, не предотвращая выполнение эффекта после этого?
3 ответов
на ngrx
инфраструктура подписывается на эффект через поставщика, импортированного в приложение NgModule
используя EffectsModule.run
.
когда наблюдаемые ошибки и catch
возвращает пустой obervable, составленный observable завершает и его подписчики отписаны-это часть Наблюдаемые Договору. И именно по этой причине вы не видите дальнейшего обращения LOGIN
действия эффекта. Эффект отписывается по завершении и the ngrx
инфраструктура не возобновите подписку.
как правило, у вас будет обработка ошибок внутри flatMap
(ныне mergeMap
):
import { Actions, Effect, toPayload } from "@ngrx/effects";
@Effect()
login$ = this.actions$
.ofType('LOGIN')
.map(toPayload)
.flatMap(payload => Observable
.from(Promise.reject('Boom!'))
.catch(error => {
console.error('Error at login', error);
return Observable.empty();
})
});
на catch
составленный во внутреннее наблюдаемое увидит пустое наблюдаемое сплющенное / объединенное В влияние, поэтому никакое действие не будет испущено.
на @Effect
поток завершение когда происходит ошибка, предотвращая любые дальнейшие действия.
решение перейти на одноразовые поток. Если в одноразовом потоке возникает ошибка, это нормально, так как main @Effect
поток всегда остается живым, и будущие действия продолжают выполняться.
@Effect()
login$ = this.actions$
.ofType('LOGIN')
.switchMap(action => {
// This is the disposable stream!
// Errors can safely occur in here without killing the original stream
return Rx.Observable.of(action)
.map(action => {
// Code here that throws an error
})
.catch(error => {
// You could also return an 'Error' action here instead
return Observable.empty();
});
});
подробнее об этой технике в этот блог: Поиск фрикадельки: продолжить RxJS потоки, когда возникают ошибки
вот как я обрабатываю опцию уведомления или не уведомления о наблюдаемых, которые не нашли никаких данных:
public listenCampaignValueChanged(emitOnEmpty: boolean = false): Observable<CampaignsModelExt> {
var campaignIdSelected$ = this.ngrxStore.select(store => store.appDb.uiState.campaign.campaignSelected)
var campaigns$ = this.ngrxStore.select(store => store.msDatabase.sdk.table_campaigns);
return campaignIdSelected$
.combineLatest(campaigns$, (campaignId: number, campaigns: List<CampaignsModelExt>) => {
return campaigns.find((i_campaign: CampaignsModelExt) => {
return i_campaign.getCampaignId() == campaignId;
});
}).flatMap(v => (v ? Observable.of(v) : ( emitOnEmpty ? Observable.of(v) : Observable.empty())));
}