Как повторно сгенерировать пойманную ошибку в блоке axios catch () - PullRequest
0 голосов
/ 22 января 2019

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

Я получаю Unhandled Rejection (Error) из-за вышеуказанного блока catch.Ниже моя сага, которая обрабатывает операцию:

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 и кода саги.

Ответы [ 3 ]

0 голосов
/ 22 января 2019

Обещание, созданное в userSignupAPI, нигде не используется (даже не возвращается), поэтому, когда в catch возникает ошибка, цепочка Обещаний преобразуется в (необдуманное) отклоненное Обещание, в результате чего ошибка.

При вызове userSignupAPI вы должны await позвонить, чтобы try / catch внутри handleUserSignup увидела выданную ошибку:

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 возвращает Promise, возвращаемое userSignupApi)

0 голосов
/ 23 января 2019

Я получил это работает.Я делал это совершенно неправильно.По предложению @certianPerformance и после прочтения некоторых вопросов и проблем с github, я нашел правильный способ справиться с этим.Вместо того, чтобы возвращать ответ API, я должен был вернуть promise.
Вот решение:

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);
}
0 голосов
/ 22 января 2019

Вы используете try catch, потому что вы не хотите выдавать ошибку в консоль браузера, которую хотите обработать в catch. Выдающая ошибка в catch удалит свое назначение. Если вы хотите выбросить ошибку, удалите try catch (что не рекомендуется)

UPDATE

Для метода axios catch перехватывает любую ошибку, выданную api url. Если вы не хотите перехватывать ошибку и показывать ее в браузере, вы можете удалить блокировку перехвата или вызвать действие, которое обрабатывает ошибку. Для получения дополнительной информации об обещании вылова вы можете обратиться здесь

...