Эффект ngrx вызывает ошибку и не срабатывает должным образом

В настоящее время я создаю компонент хлебных крошек ngrx в angular 5.2.1, используя ngrx 4.1.1. Это незавершенная работа, поэтому мне еще нужно исправить некоторые детали.

В настоящее время я получаю сообщение об ошибке в эффекте изменения. Ошибка:

Эффект «BreadcrumbEffects.breadcrumbs $» выдал ошибку Источник: BreadcrumbEffects

Ошибка: TypeError: вы указали undefined там, где ожидался поток. Вы можете предоставить Observable, Promise, Array или Iterable.

Я получаю сообщение об ошибке только после добавления в существующее состояние с помощью оператора withLatestFrom. До этого у меня не было оператора withLatestFrom, а вместо оператора map у меня был оператор switchMap, и он работал нормально. Что я делаю неправильно?

Мой эффект заявлен следующим образом.

/* Effects handle the actual execution of the action */
import { Injectable } from "@angular/core";
import { BreadcrumbService } from "./breadcrumb.service";
import { Observable } from "rxjs/Observable";
import * as moment from "moment";
import { Action, Store } from "@ngrx/store";
import { Effect, Actions } from "@ngrx/effects";
import { BreadcrumbActionTypes, ChangeBreadcrumbsAction, ChangeBreadcrumbsCompleteAction } from "./breadcrumb.actions";
import * as fromBreadcrumbReducer from "./breadcrumb.reducers";

@Injectable()
export class BreadcrumbEffects {

    crumbs$: Observable<any>;

    constructor(private readonly actions$: Actions,
        private readonly store$: Store<fromBreadcrumbReducer.BreadcrumbState>,
        private readonly breadcrumbService: BreadcrumbService) {

        this.crumbs$ = this.store$.select(fromBreadcrumbReducer.Selectors.getBreadcrumbs);
    }

    @Effect()
    breadcrumbs$: Observable<ChangeBreadcrumbsCompleteAction> =
    this.actions$
        .ofType(BreadcrumbActionTypes.ChangeBreadcrumbs)
        .withLatestFrom(this.crumbs$)
        .map((result: any) => {
            let action: ChangeBreadcrumbsAction, crumbs: any[];
            [action, crumbs] = result;
            /* make a copy of the existing crumbs. */
            /* this code is still being worked on, hence the hardcoded index */
            const newCrumbs = crumbs.slice(0);
            if (crumbs.length > 0) {
                newCrumbs[1] = { ...newCrumbs[1], displayName: action.name }
            }
            return new ChangeBreadcrumbsCompleteAction(newCrumbs);
        });
}

person tone    schedule 24.01.2018    source источник


Ответы (1)


Проблема в том, что this.crumbs$ передается в withLatestFrom(this.crumbs$), но он не будет определен до тех пор, пока не будет назначен в конструкторе.

Вы можете решить проблему с помощью defer:

import { defer } from "rxjs/observable/defer";
...
.withLatestFrom(defer(() => this.crumbs$))

Или объявив свой эффект с помощью функции:

@Effect()
breadcrumbs$(): Observable<ChangeBreadcrumbsCompleteAction> {
  return this.actions$
    .ofType(BreadcrumbActionTypes.ChangeBreadcrumbs)
    .withLatestFrom(this.crumbs$)
    .map((result: any) => {
      let action: ChangeBreadcrumbsAction, crumbs: any[];
      [action, crumbs] = result;
      /* make a copy of the existing crumbs. */
      /* this code is still being worked on, hence the hardcoded index */
      const newCrumbs = crumbs.slice(0);
      if (crumbs.length > 0) {
        newCrumbs[1] = { ...newCrumbs[1], displayName: action.name }
      }
      return new ChangeBreadcrumbsCompleteAction(newCrumbs);
});
person cartant    schedule 24.01.2018
comment
Спасибо, вот в чем проблема! Я изменил оператор withLatestFrom на: .withLatestFrom (this.store $ .select (fromBreadcrumbReducer.Selectors.getBreadcrumbs)), который согласуется с другими примерами, и решил проблему. - person tone; 25.01.2018