Как обрабатывать необработанные ошибки отказа с помощью axios

Axios - отличная библиотека, но необработанные отказы от обещаний могут стать проблемой. Как от них избавиться?

TL;DR

Используйте этот перехватчик:

axios.interceptors.response.use(
  response => response,
  error => {
    throw error
  }
)

Предыстория

Я сегодня просматривал свои отчеты об ошибках на Honeybadger и наткнулся на следующее:

Если вы похожи на меня, вы смотрите на это мышление ... Хорошо, но что пошло не так? Что касается Honeybadger, ошибка заключается в том, что мы не обработали отказ от обещания. Однако настоящая проблема в том, что axios отклонены из-за неудавшегося запроса. К сожалению, мы не можем сказать, в чем заключалась ошибка, потому что она скрыта за этой unhandledrejection ошибкой.

Что такое принятое решение?

Я пошел искать решение и наткнулся на эту проблему Github, которая привела меня на верный путь.

Svpace упомянул, что они использовали этот перехватчик:

axios.interceptors.response.use(
  response => response,
  error => {
    console.log(error.message);
    return Promise.reject(error);
}

но это не сработало, как они ожидали. Они все еще сталкивались с unhandledrejection ошибкой.

Я попытался использовать этот перехватчик и увидел точно такой же результат, что и они, что имеет смысл.

Почему это не работает?

Если вы посмотрите на перехватчик, мы обрабатываем отказ. В этом обработчике мы записываем сообщение об ошибке и переходим к следующему этапу. К сожалению, следующее, что делает перехватчик, - это еще один отказ. Этот отказ возвращает нас с того места, где мы начали, с необработанным отказом.

Код

Ваши запросы axios должны выглядеть следующим образом:

const response =
  await axios.get("/some/path/or/url").catch(yourErrorHandler)

or

try {
  const response = await axios.get("/some/path/or/url")
} catch (e) {
  yourErrorHandler(e)
}

Мой обработчик ошибок выглядит так:

export function handleError(e) {
  if (typeof Honeybadger !== "undefined") {
    Honeybadger.notify(e)
  } else {
    throw e
  }
}

Кроме того, я использую try / catch версию приведенного выше кода.

Исходя из этого, вы можете видеть, что мой axios.get вызов завершился неудачно, а e в блоке catch - это unhandledrejection ошибка, а не обнаруженные аксиомы ошибки. Затем об этой ошибке сообщается Honeybadger.

Какое решение подойдет нам?

Как я уже упоминал, проблема с Github поставила меня на верный путь. Мы определенно хотим использовать перехватчик, поскольку это единственный известный мне способ справиться с отказом. А как же должен выглядеть наш перехватчик?

Во-первых, мы хотим передать успешные решения, поэтому начнем с этого:

axios.interceptors.response.use(response => response)

Далее нам нужно добавить обработчик отклонения:

axios.interceptors.response.use(
  response => response,
  error => {}
)

Что нам делать в этом обработчике? Давайте подумаем о наших целях:

  1. Избавьтесь от ошибки unhandledrejection.
  2. Выявите фактическую ошибку в нашем Promise.catch вызове или в блоке catch, если вы используете_11 _ / _ 12_.

Способ сделать это - повторно выбросить исходную ошибку, а не отклонять ее снова. Для этого мы можем обновить перехватчик, чтобы он выглядел так:

axios.interceptors.response.use(
  response => response,
  error => {
    // We really want to throw the error so it is handled and we
    // don't get an unhandledrejection error. By throwing here, we
    // are handling the rejection, and bubbling up to the closest
    // error handler (try/catch or catch method call on a promise).
    throw error
  }
)

Спасибо за чтение, друг

Надеюсь, вам понравилась эта статья, удачного дня!

Первоначально опубликовано на https://brandoncc.dev.