【问题标题】:ngrx effects error handlingngrx 影响错误处理
【发布时间】:2017-01-16 21:47:29
【问题描述】:

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

,但这会导致死循环……你知道如何在不阻止效果执行的情况下捕获错误吗?

【问题讨论】:

  • 我不知道ngrx,但你可以只在流中.retry() 而不是捕捉。
  • 你使用的ngrx是什么版本?我用最新版本的ngrx试过这个,似乎它不起作用..版本,我现在正在使用:“@ngrx/core”:“^1.2.0”,“@ngrx/effects”:“^6.1.2”, "@ngrx/entity": "^6.1.2", "@ngrx/store": "^6.1.2",

标签: rxjs ngrx


【解决方案1】:

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

当 observable 错误和 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 被展平/合并到效果中,因此不会发出任何操作。

【讨论】:

    【解决方案2】:

    当错误发生时,@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

    【讨论】:

      【解决方案3】:

      这就是我在未找到任何数据的 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())));
          }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-03-17
        • 2019-01-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多