эффект ngrx не вызывается при отправке действия из компонента

у меня проблема с магазином ngrx, не отправляющим действие на эффект, который должен иметь с ним дело.

вот компонент, который пытается отправить:

  signin() {
    this.formStatus.submitted = true;
    if (this.formStatus.form.valid) {
      this.store.dispatch(new StandardSigninAction(this.formStatus.form.value.credentials));
    }
  }

действия:

export const ActionTypes = {
  STANDARD_SIGNIN: type('[Session] Standard Signin'),
  LOAD_PERSONAL_INFO: type('[Session] Load Personal Info'),
  LOAD_USER_ACCOUNT: type('[Session] Load User Account'),
  RELOAD_PERSONAL_INFO: type('[Session] Reload Personal Info'),
  CLEAR_USER_ACCOUNT: type('[Session] Clear User Account')
};

export class StandardSigninAction implements Action {
  type = ActionTypes.STANDARD_SIGNIN;

  constructor(public payload: Credentials) {
  }
}
...

export type Actions
  = StandardSigninAction
  | LoadPersonalInfoAction
  | ClearUserAccountAction
  | ReloadPersonalInfoAction
  | LoadUserAccountAction;

эффект:

  @Effect()
  standardSignin$: Observable<Action> = this.actions$
    .ofType(session.ActionTypes.STANDARD_SIGNIN)
    .map((action: StandardSigninAction) => action.payload)
    .switchMap((credentials: Credentials) =>
      this.sessionSigninService.signin(credentials)
        .map(sessionToken => {
          return new LoadPersonalInfoAction(sessionToken);
        })
    );

Я вижу в debug, что компонент вызывает метод dispatch. Я также могу подтвердить, что StandardSigninAction действительно создается экземпляр, потому что точка останова в конструкторе попадает.

но standardSignin$ эффект не называется...

что может вызвать эффект не вызывается?

как я могу отлаживать, что происходит в магазине?

может кто-нибудь помочь?

P. S. Я не запустите указанный выше эффект следующим образом в моем импорта:

EffectsModule.run(SessionEffects),

редактировать: вот мой SessionSigninService.метод signin (возвращает наблюдаемый)

  signin(credentials: Credentials) {
    const headers = new Headers({'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'});
    const options = new RequestOptions({headers: headers});
    const body = 'username=' + credentials.username + '&password=' + credentials.password;
    return this.http.post(this.urls.AUTHENTICATION.SIGNIN, body, options).map(res => res.headers.get('x-auth-token'));
  }

2 ответов


это не будет окончательным ответом, но, надеюсь, это будет полезно.

прежде чем начать:

  • убедитесь, что вы используете последние версии @ngrx пакеты (которые подходят для версии Angular, которую вы используете).
  • если вы обновили какие-либо пакеты, убедитесь, что вы повторно запустите среду разработки (то есть перезапустите bundler, сервер и т. д.)

если вы еще не сделали этого уже, вы должны взглянуть на реализация Store - так что вы делаете некоторые обоснованные догадки о том, что может пойти не так. Обратите внимание, что Store довольно светлая. Это и наблюдаемый (используя состояние как его источник), и наблюдатель (который ссылается на диспетчера).

если вы посмотрите на store.dispatch вы увидите, что это псевдоним store.next, которая называет next на Dispatcher.

так зовет:

this.store.dispatch(new StandardSigninAction(this.formStatus.form.value.credentials));

должен просто видеть действие, излучаемое диспетчером.

на Actions наблюдаемый, который вводится в ваши эффекты, также довольно легкий. Это просто наблюдаемый, который использует Dispatcher в качестве источника.

чтобы посмотреть на действия, которые протекают через эффект, вы можете заменить это:

@Effect()
standardSignin$: Observable<Action> = this.actions$
  .ofType(session.ActionTypes.STANDARD_SIGNIN)

С это:

@Effect()
standardSignin$: Observable<Action> = this.actions$
  .do((action) => console.log(`Received ${action.type}`))
  .filter((action) => action.type === session.ActionTypes.STANDARD_SIGNIN)

ofType не является оператором; это метод, поэтому добавьте do-на основе ведения журнала, его необходимо заменить на filter.

при регистрации на месте, если вы получаете действие, что-то не так с реализацией эффекта (или, возможно, строки/константы типов действий не то, что вы думаете, и что-то не соответствует).

если эффект не получает отправленное действие, наиболее вероятно объяснением было бы то, что store через который вы отправляете StandardSigninAction - это не то же store что ваш эффект использует - то есть, у вас есть проблема DI.

если это так, вы должны посмотреть, что отличается от других SessionEffects что вы говорите работают. (По крайней мере, у вас есть что-то работающее, что является хорошим местом для начала экспериментов.) Они отправляются из другого модуля? Это модуль, который отправляет StandardSigninAction функция модуль?

что произойдет, если вы взломаете один из рабочих SessionEffects чтобы заменить его отправленное действие на StandardSigninAction? Затем эффект запускается?


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

например, это убьет поток:

this.actions$
    .ofType('FETCH')
    .map(a => a.payload)
    .switchMap(query => this.apiService.fetch$(query)
        .map(result => ({ type: 'SUCCESS', payload: result }))
        .catch(err => console.log(`oops: ${err}`))) // <- breaks stream!

но это сохранит жизнь:

this.actions$
    .ofType('FETCH')
    .map(a => a.payload)
    .switchMap(query => this.apiService.fetch$(query)
        .map(result => ({ type: 'SUCCESS', payload: result }))
        .catch(e => Observable.of({ type: 'FAIL', payload: e}))) // re-emit

это верно для любого RxJS наблюдаемого btw, что особенно важно учитывать при трансляции в несколько наблюдателей (например, ngrx store делает внутренне, используя внутренний Subject).