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

kx7yvsdv  于 2023-08-04  发布在  iOS
关注(0)|答案(4)|浏览(189)

axios中,为什么throw new Error()不允许在catch()中使用?我在这样的要求,如果一个错误是由服务器返回,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)。下面是我的 Saga ,它处理的操作:

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 代码进行单元测试变得容易。

mbyulnm0

mbyulnm01#

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

字符串
(make确保call返回userSignupApi返回的Promise

rfbsl7qr

rfbsl7qr2#

我把它修好了。我做得完全不对。根据@certianPerformance的建议,在阅读了一些问题和github问题后,我找到了正确的处理方法。我应该返回promise,而不是返回API响应。

解决方案如下:

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

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

字符串
Saga :

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

jfewjypa

jfewjypa3#

我一直在找这个,但没有找到答案。这是我发现的第一个问题。
我认为在特定情况下捕获并重新抛出错误以使其冒泡是完全有效的,例如,我一直在使用可观察数据。
无论如何,对我有效的只是返回一个Promise。reject(err)

// inside a function block
 try {
    axios.post(endpoint, userDetails)
 } catch (err) {
    if (err.code === 409) {
       // for example convert to a 200 with an error message
       return { error: { message: 'oops, conflict!'} };
    }
    // this to catch the exact same error later on
    return Promise.reject(err);

 }

字符串

piok6c0g

piok6c0g4#

您使用try catch是因为您不想在catch中处理的浏览器控制台中抛出错误。在catch中抛出错误将删除它的用途。如果你想抛出错误,请删除try catch(这不是推荐的方法)

更新

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

相关问题