首页 > 解决方案 > 在 Ionic 3 中的 NgRx 中传递错误 URL 时,减速器错误始终未定义

问题描述

有人可以帮我看看这里有什么问题,每次我尝试导致错误时都会得到: 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;

然后我有一个服务来调用一个休息服务,它将返回一个 Observable 到效果:

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

然后我有两种方法:一种是发送动作,另一种是返回状态:

  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
  }
});

正如您在下图中看到的那样,错误发生了,但从未使用该操作捕获和传递: 在此处输入图像描述

我知道这很多,但如果有人能注意到任何东西并将其指向我,我将非常感激。

标签: angularreduxionic3ngrx

解决方案


我怀疑当您的效果“catchError”运算符返回 of(....) 时是否正在调用您的减速器。事实上,你必须返回一个动作,如 -

@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})])
    );

推荐阅读