在 Ionic 3 的 NgRx 中传递错误 URL 时,Reducer 错误始终未定义

Reducer error always undefined when passing wrong URL in NgRx in Ionic 3

谁能帮我看看这里出了什么问题,每次我尝试导致错误时,我都会得到: core.js:12632 ERROR TypeError: Cannot read property 'error' of undefined

我的效果:

  @Effect() loadByEmail = this.actions
    .pipe(
      ofType(ProfileActions.ActionTypes.Begin),
      map((action: ProfileActions.LoadProfileBegin) => action),
      switchMap(action => this.service.loadByEmail(action.email, true)),
      map(response => ({
        type: ProfileActions.ActionTypes.Success,
        payload: response,
        error: null
      })),
      catchError((error) => of ({
        type: ProfileActions.ActionTypes.Failure,
        error: error
      }))
    );

减速器:

export interface ProfileState {
  payload: any;
  loading: boolean;
  error: any;
}

const initialState: ProfileState = {
  loading: false,
  error: null,
  payload: null
};

export function profileReducer(state = initialState, action: profileActions.ActionsUnion): ProfileState {
  switch (action.type) {

    case profileActions.ActionTypes.Begin: {
      return {
        ...state,
        loading: true,
        error: null
      };
    }

    case profileActions.ActionTypes.Success: {
      return {
        ...state,
        loading: false,
        payload: action.payload.data
      };
    }

    case profileActions.ActionTypes.Failure: {
      return {
        ...state,
        loading: false,
        error: action.payload.error /* this is the line 49*/
      };
    }

    default: {
      return state;
    }
  }
}

export const getProfile = (state: ProfileState) => state.payload;

我想我可能在这里犯了一些大错误导致了这个问题,我需要在订阅时捕获错误。

这是操作,实际上这是一个非常基本的东西,它只是一个通过电子邮件地址从 Web 服务加载配置文件的流程。

以下是三个动作:

export enum ActionTypes {
  Begin = "[Profile] Load data begin",
    Success = "[Profile] Load data success",
    Failure = "[Profile] Load data failure"
}

export class LoadProfileBegin implements Action {
  readonly type = ActionTypes.Begin;
  constructor(public email: string) {}
}

/**
 * The main thing to note here is that our LoadDataSuccess and 
 * LoadDataFailure actions will include a payload - we will either 
 * pass the loaded data along with LoadDataSuccess or we will 
 * pass the error to LoadDataFailure.
 */
export class LoadProfileSuccess implements Action {
  readonly type = ActionTypes.Success;

  constructor(public payload: {
    data: any
  }) { }
}

export class LoadProfileFailure implements Action {
  readonly type = ActionTypes.Failure;

  constructor(public payload: {
    error: any
  }) { }
}

export type ActionsUnion = LoadProfileBegin | LoadProfileSuccess | LoadProfileFailure;

然后我有一个调用休息服务的服务,它将 return 一个可观察到的效果:

  public loadByEmail(email: string, showLoading ? : boolean): Observable < any > {
    const data: any = {
      'email': email
    };
    return <Observable < any >> this.restService.sendPost('profiles__/find-by-email', data);
  }

然后我有两种方法:一种是分派动作,另一种是 return 状态:

  loadProfileState(email: string) {
    this.store.dispatch(new ProfileActions.LoadProfileBegin(email));
  }

  getProfileState(): Store < ProfileState > {
    return this.store.select(getProfileState);
  }

然后在我订阅的某个组件中尝试捕获错误:

this.profileService.getProfileState().subscribe(state => {
  if (state.payload) {
    const profile = state.payload.json;
    this.setProfileData(profile, true);
  } 

  if (state.error){
    // This one here never reaches
  }
});

正如您在下图中看到的,错误发生但从未使用操作捕获和传递:

我知道很多,但如果有人能注意到任何东西并指给我看,我将不胜感激。

我怀疑当你的 effect "catchError" operator returns of(....) 时你的 reducer 被调用了。事实上,您必须 return 像这样的操作 -

@Effect() loadByEmail = this.actions
    .pipe(
      ofType(ProfileActions.ActionTypes.Begin),
      map((action: ProfileActions.LoadProfileBegin) => action),
      switchMap(action => this.service.loadByEmail(action.email, true)),
      map(response => ({
        type: ProfileActions.ActionTypes.Success,
        payload: response,
        error: null
      })),
      catchError((error) => [new ProfileActions.LoadProfileFailure({error})])
    );