如何重新抛出 axios catch() 块中捕获的错误

How to re-throw the catched error in axios catch() block

axios中,为什么catch()里面不允许throw new Error()? 我有这样的要求,如果服务器返回错误,catch 块应该抛出一个错误,稍后将由 redux-saga 处理并派发适当的操作。

API调用:

export const userSignupApi = userDetails => {
   const endpoint = `${URL_ROOT}${URN_SIGNUP}`;
    axios
    .post(endpoint, userDetails)
    .then(response => {
      console.log("Response: ", response);
      //do something with the response
    })
    .catch(error => {
      throw new Error(error.response.data.message);
    });
};

由于上面的 catch 块,我得到了 Unhandled Rejection (Error)。 下面是我处理操作的传奇:

import { call, takeLatest, put } from "redux-saga/effects";

function* handleUserSignup(action) {
  try {
    yield call(userSignupApi, action.userDetails);
    yield put(userSignupSuccess()); //dispatching success action
  } catch (error) {
    yield put(userSignupFail(error)); //dispatching error action
  }
}

function* watchUserSignup() {
  yield takeLatest(NEW_USER.SIGNUP, handleUserSignup);
}

编辑:为什么我要上面的代码结构?因为这使得对 API 代码和 saga 代码进行单元测试变得容易。

您正在使用 try catch,因为您不想在浏览器控制台中抛出要在 catch 中处理的错误。在 catch 中抛出错误将移除它的 purpose.If 你想要抛出错误移除 try catch(这不是推荐的方式)

更新

对于 axios,catch 方法捕获 api url 抛出的任何错误。如果你不想捕获错误并在浏览器中显示它,你可以删除 catch 块或者你可以调用处理错误的操作。有关 promise catch 的更多信息,您可以参考 here

userSignupAPI 中创建的 Promise 没有在任何地方使用(它甚至没有被返回),所以当在 catch 中抛出错误时,Promise 链解析为(未捕获的)拒绝了 Promise,导致错误。

userSignupAPI 的调用者中,你应该 await 调用,这样 handleUserSignup 里面的 try/catch 就会看到抛出的错误:

export const userSignupAPI = userDetails => {
   const endpoint = `${URL_ROOT}${URN_SIGNUP}`;
    return axios
    .post(endpoint, userDetails)
    .then(response => {
      console.log("Response: ", response);
    })
    .catch(error => {
      throw new Error(error.response.data.message);
    });
};

async function* handleUserSignup(action) {
  try {
    yield await call(userSignupApi, action.userDetails);
    yield put(userSignupSuccess()); //dispatching success action
  } catch (error) {
    yield put(userSignupFail(error)); //dispatching error action
  }
}

function* watchUserSignup() {
  yield takeLatest(NEW_USER.SIGNUP, handleUserSignup);
}

(确保 call returns userSignupApi 返回的 Promise

我成功了。我做的完全错了。正如@certianPerformance 所建议的那样,在阅读了一些问题和 github 问题之后,我找到了处理这个问题的正确方法。我应该返回 promise.
而不是返回 api 响应 解决方法如下:

export const userSignupApi = userDetails => {
  const endpoint = `${URL_ROOT}${URN_SIGNUP}`;

  return axios.post(endpoint, userDetails);
};

传奇:

import { call, takeLatest, put } from "redux-saga/effects";

function* handleUserSignup(action) {
  try {
    const response = yield call(userSignupApi, action.userDetails);
    response.then(response => {
      const location = response.headers.location;
      put(userSignupSuccess(location));
      put(newUserWelcomeNote("Welcome user"));
    });
  } catch (error) {
    const errorMessage = error.response.data.message;
    yield put(userSignupFail(errorMessage));
  }
}

function* watchUserSignup() {
  yield takeLatest(NEW_USER.SIGNUP, handleUserSignup);
}