@ngrx带有效果的无限调用动作

时间:2018-10-25 19:30:26

标签: ngrx ngrx-store ngrx-effects

如果这是一个简单的答案,请原谅我。我有一个复杂的登录逻辑,在用户拥有完整的配置文件之前,需要几次调用。如果某个步骤失败,则不应破坏应用程序-用户只是无法获得一些补充信息。

我要实现的流程是这样的:

  1. 致电Revalidate
  2. Revalidate会同时调用RevalidateSuccessProfileGet(通过提取来增强用户状态)。
  3. ProfileGetSuccess

为节省大量代码,存在操作(这是一个巨大的文件)。

该应用开始执行操作:this._store.dispatch(new Revalidate())

从那里开始,我们将产生以下效果:

@Effect()
public Revalidate: Observable<any> = this._actions.pipe(
  ofType(AuthActionTypes.REVALIDATE),
  map((action: Revalidate) => action),
  // This promise sets 'this._profile.currentProfile' (an Observable)
  flatMap(() => Observable.fromPromise(this._auth.revalidate())),
  // Settings are retrieved as a promise
  flatMap(() => Observable.fromPromise(this._settings.get())),
  switchMap(settings => 
    // Using map to get the current instance of `this._profile.currentProfile`
    this._profile.currentProfile.map(profile => {
      const onboarded = _.attempt(() => settings[SettingsKeys.Tutorials.Onboarded], false);
      return new RevalidateSuccess({ profile: profile, onboarded: onboarded });
  }))
);

//Since I couldn't get it working using concatMap, trying NOT to call two actions at once
@Effect()
public RevalidateSuccess: Observable<any> = this._actions.pipe(
  ofType(AuthActionTypes.REVALIDATE_SUCCESS),
  mapTo(new ProfileGet)
);

@Effect()
public ProfileGet: Observable<any> = this._actions.pipe(
  ofType(AuthActionTypes.PROFILE_GET),
  // We need to retrieve an auth key from storage
  flatMap(() => Observable.fromPromise(this._auth.getAuthorizationToken(Environment.ApiKey))),
  // Now call the service that gets the addt. user data.
  flatMap(key => this._profile.getCurrentProfile(`${Environment.Endpoints.Users}`, key)),
  // Send it to the success action.
  map(profile => {
  console.log(profile);
  return new ProfileGetSuccess({});
  })
);

减速器:

export function reducer(state = initialState, action: Actions): State 
{
  switch (action.type) {
    case AuthActionTypes.REVALIDATE_SUCCESS:
      console.log('REVALIDATE_SUCCESS');
      return {
        ...state,
        isAuthenticated: true,
        profile: action.payload.profile,
        onboarded: action.payload.onboarded
      };
    case AuthActionTypes.PROFILE_GET_SUCCESS:
      console.log('PROFILE_GET_SUCCESS');
      return { ...state, profile: action.payload.profile };
    case AuthActionTypes.INVALIDATE_SUCCESS:
      return { ...state, isAuthenticated: false, profile: undefined };
    default:
      return state;
  }
}

正如标题所述,调度动作是无限运行的。谁能指出我正确的方向?

1 个答案:

答案 0 :(得分:0)

答案就在这里

this._profile.currentProfile.map必须为this._profile.currentProfile.take(1).map。问题不是我的所有动作都被调用的事实,而是因为我是在可观察对象上运行一个动作,所以我想每次有人触摸可观察对象时,它都会重新运行该动作,而这恰好是无限次。

此外,我能够重构动作存储,以便摆脱其他动作来调用以获取用户的其余数据,而订阅this._profile.currentProfile并调用基于非效果的动作,ProfileSet,当可观察值改变时。这让我删除了6个动作(因为它们是异步调用并且需要成功/失败的伴随动作),所以这是一个很大的胜利。