ngrx 影响错误处理
ngrx effects error handling
我有一个关于@ngrx 效果的非常基本的问题:如何忽略效果执行期间发生的错误,使其不影响未来的效果执行?
我的情况如下:我有一个动作(LOGIN)和一个监听那个动作的效果。如果此效果内部发生错误,我想忽略它。发生此错误后第二次调度 LOGIN 时,应执行第二次效果。
我第一次尝试这样做是:
@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();
});
如预期的那样,第一次调度 LOGIN 会抛出并捕获错误。但是,如果我之后第二次发送 LOGIN,什么也不会发生;效果不执行。
因此我尝试了以下方法:
.catch(err => {
return this.login$;
});
,但这会导致死循环...你知道如何在不阻止 effect 执行的情况下捕获错误吗?
ngrx
基础设施通过使用 EffectsModule.run
.
导入到应用 NgModule
的提供商订阅效果
当 observable 错误和 catch
returns 一个空的 obervable 时,组合的 observable 完成并且它的订阅者被取消订阅 - 这是 Observable Contract 的一部分。这就是您在效果中看不到 LOGIN
操作没有进一步处理的原因。效果在完成时取消订阅,ngrx
基础设施不会 re-subscribe。
通常,您会在 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
将在效果中看到一个空的可观察对象 flattened/merged,因此不会发出任何动作。
这就是我如何处理在未找到任何数据的 Observables 上通知或不通知的选项:
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())));
}
当发生错误时,@Effect
流正在完成,阻止任何进一步的操作。
解决方案是切换到一次性流。如果在一次性流中发生错误也没关系,因为主 @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();
});
});
此博客中有关此技术的更多信息 post:The Quest for Meatballs: Continue RxJS Streams When Errors Occur
我有一个关于@ngrx 效果的非常基本的问题:如何忽略效果执行期间发生的错误,使其不影响未来的效果执行?
我的情况如下:我有一个动作(LOGIN)和一个监听那个动作的效果。如果此效果内部发生错误,我想忽略它。发生此错误后第二次调度 LOGIN 时,应执行第二次效果。
我第一次尝试这样做是:
@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();
});
如预期的那样,第一次调度 LOGIN 会抛出并捕获错误。但是,如果我之后第二次发送 LOGIN,什么也不会发生;效果不执行。
因此我尝试了以下方法:
.catch(err => {
return this.login$;
});
,但这会导致死循环...你知道如何在不阻止 effect 执行的情况下捕获错误吗?
ngrx
基础设施通过使用 EffectsModule.run
.
NgModule
的提供商订阅效果
当 observable 错误和 catch
returns 一个空的 obervable 时,组合的 observable 完成并且它的订阅者被取消订阅 - 这是 Observable Contract 的一部分。这就是您在效果中看不到 LOGIN
操作没有进一步处理的原因。效果在完成时取消订阅,ngrx
基础设施不会 re-subscribe。
通常,您会在 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
将在效果中看到一个空的可观察对象 flattened/merged,因此不会发出任何动作。
这就是我如何处理在未找到任何数据的 Observables 上通知或不通知的选项:
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())));
}
当发生错误时,@Effect
流正在完成,阻止任何进一步的操作。
解决方案是切换到一次性流。如果在一次性流中发生错误也没关系,因为主 @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();
});
});
此博客中有关此技术的更多信息 post:The Quest for Meatballs: Continue RxJS Streams When Errors Occur