@ngrx Действие называется бесконечно с эффектами - PullRequest
0 голосов
/ 25 октября 2018

Пожалуйста, прости меня, если это простой ответ.У меня сложная логика входа в систему, которая требует нескольких звонков, прежде чем у пользователя будет полный профиль.Если какой-то шаг завершается неудачей, он не должен нарушать работу приложения - пользователь просто не получает дополнительную информацию.

Поток, которого я ищу, заключается в следующем:

  1. Звоните Revalidate.
  2. Revalidate звонки RevalidateSuccess, а также ProfileGet(дополнительная выборка для улучшения состояния пользователя).
  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 голосов
/ 26 октября 2018

Ответ лежит здесь:

this._profile.currentProfile.map должно быть this._profile.currentProfile.take(1).map.Проблема заключалась не в том, что все мои действия были вызваны, а потому, что я выполнял действие на наблюдаемой, я полагаю, что оно повторялось действие каждый раз, когда кто-то касался наблюдаемой, что случалось бесконечно.

Кроме того, я смог реорганизовать свое хранилище действий, чтобы я мог избавиться от других своих действий для вызова, чтобы получить остальную часть данных пользователя, вместо этого подписавшись на this._profile.currentProfile и вызвав бездействие на основедействие, ProfileSet, когда значение наблюдаемого изменилось.Это позволило мне удалить 6 действий (так как они были асинхронными вызовами и требовали сопутствующих действий успеха / неудачи), так что это был довольно большой выигрыш.

...