【问题标题】:Service methods firing multiple times when using new Ngrx 8 createEffect pattern使用新的 Ngrx 8 createEffect 模式时多次触发服务方法
【发布时间】:2019-12-10 12:40:43
【问题描述】:

在将某些功能 Effects 切换到新的 createEffct() 模式后,它们调用的所有服务请求现在都会在我的控制台输出中触发两次。

下面是动作:

export const getSetting = createAction(
  '[Practitioner Settings] Get Setting',
  props<{ name: string }>(),
);

这是一个使用旧语法的效果示例:

@Effect()
getSetting$: Observable<Action> = this.actions.pipe(
  ofType(PractitionerSettingsActionTypes.GetSetting),
  map((action: PractitionerSettingsActions.GetSetting) => action.name),
  switchMap((name: string) => {
    return this.practitionerSetingsService
               .getSetting(name)
               .pipe(
                 map(response => new PractitionerSettingsActions.GetSettingSuccess(response)),
               )
    }),
  );

以及新语法,基于以下示例:https://github.com/ngrx/platform/blob/master/projects/example-app/src/app/books/effects/collection.effects.ts:

@Effect()
getSetting = createEffect(() =>
  this.actions.pipe(
    ofType(PractitionerSettingsActions.getSetting),
    mergeMap(({ name }) => {
      return this.practitionerSetingsService
                 .getSetting(name)
                 .pipe(
                    map(response => PractitionerSettingsActions.getSettingSuccess({ setting: response })),
                  )
      }),
    )
  );

我怀疑是 mergeMap 运算符导致了这种行为,因为它是两者之间的唯一区别,但我不确定它为什么会导致这种情况,或者如何以其他方式访问操作的有效负载。

除了将 Ngrx Actions、Reducers 和 Effects 更新为 v8 模式之外,我没有对我的应用程序进行任何其他更改,这会导致服务调用被执行两次。

如果不是 mergeMap,我应该使用什么运算符来访问操作负载?如果 mergeMap 是正确的,为什么我的效果会运行不止一次?

【问题讨论】:

  • 作为测试,您可以在某处添加this.actions.subscribe((action) =&gt; console.log(action)) 吗?这样,如果您的操作多次触发,您可以缩小范围。 switchMap 一次只允许一个内部订阅处于活动状态。一旦有新订阅,它就会取消任何活动的内部订阅。mergeMap 没有这种相同的取消效果。每个内部订阅都会运行。 learnrxjs.io/operators/transformation/mergemap.htmllearnrxjs.io/operators/transformation/switchmap.html
  • 让我试一试
  • 我在每个服务方法中都添加了一个日志语句。将 mergeMap 更改为 switchMap 会产生相同的结果。对于 Effect 调用的每个方法,我仍然在控制台中看到我的日志语句两次。
  • 为了验证,我切换到我的开发分支,用旧模式运行代码,每个服务方法我只看到一个日志语句。

标签: angular ngrx ngrx-effects


【解决方案1】:

如果您检查链接的示例,@Effect() 注释不存在,并且它存在于问题代码中。我认为这就是它以这种方式为您工作的原因

【讨论】:

  • 只是为了澄清其他人。当您使用 createEffect() 时,您不再需要 @Effect() 装饰器
  • 我看到了同样的问题,我们只使用 createEffect() 而没有 @Effect()
  • 你在任何地方注册了你的效果类吗?
猜你喜欢
  • 2021-07-21
  • 1970-01-01
  • 2020-10-11
  • 2019-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多