首页 文章

ngrx影响错误处理

提问于
浏览
21

我有一个关于@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$;
    });

,但这导致无限循环......你知道如何捕获错误而不会阻止效果执行吗?

3 回答

  • 1

    发生错误时 @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();
                });
    
        });
    

    有关此技术的更多信息,请参阅此博客文章:The Quest for Meatballs: Continue RxJS Streams When Errors Occur

  • 4

    这就是我如何处理在没有找到任何数据的Observable上通知或不通知的选项:

    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())));
        }
    
  • 18

    ngrx 基础设施通过使用 EffectsModule.run 导入应用程序 NgModule 的提供程序订阅效果 .

    当可观察的错误和 catch 返回一个空的obervable时,组合的observable完成并且其订阅者被取消订阅 - 这是Observable Contract的一部分 . 这就是你认为没有进一步处理 LOGIN 动作的原因 . 该效果在完成时取消订阅, 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();
        })
      });
    

    组成内部observable的 catch 将看到一个空的observable展平/合并到效果中,因此不会发出任何动作 .

相关问题