zukucode
主にWEB関連の情報を技術メモとして発信しています。

async/awaitでajax(axios)処理のエラー時の処理を考える

async,awaitを使った非同期処理(特にajax処理)の実装でエラー時の処理をどのように実装したらいいか、いろいろと調べてみました。

try-catchを使う方法

最初は以下のように、awaitの処理をtry-catchで囲う方法で実装しました。

let response;
try {
  response = await ajax();
} catch (e) {
  console.log('エラー発生');
  return;
}
console.log(response);

この方法だと、tryの中に複数のawaitの処理があった場合、catchに入った時にどのawait処理でエラーになったのかというのがわからないです。(サーバー処理でエラー時のレスポンスデータに工夫が必要になる)

個々のawait処理をtry-catchで囲うのならPromiseで実装したほうがスッキリする気もするので、他の方法を考えました。

responseデータで正常終了したかどうか判定する

サーバー処理では各処理ごとに個別にtry-catchで囲ったりせずに、グローバルレベルで1箇所にエラー処理を実装することが多かったのですが、JavaScriptの場合は考え方が少し違うように感じました。

ajax処理ではサーバー処理でのバリデーションエラーやネットワーク環境によるエラーなど、想定するべきエラーがたくさんあるので、サーバー処理のように、「エラー時はエラー画面に飛ばす」などのようにエラー時の処理を共通化するのは難しいです。

バリデーションエラーなどの処理をcatch処理で実装するのは違和感があったので、このような想定されたエラーの場合、ajax処理自体は正常終了するようにして、responseのデータによってエラーかどうか判定する方法がいいと思いました。

ajaxライブラリの修正

ajaxライブラリのレスポンス時の処理を修正します。

ajaxライブラリにaxiosを使用してる場合は、interceptors.responseの処理を実装します。

正常時、エラー時ともに、Promiseは成功として扱い、オブジェクトを返すようにします。

正常時はdata、エラー時はerrorをオブジェクトにセットしています。

axios.interceptors.response.use((response) => {
  return Promise.resolve({
    data: response.data
  });
}, (error) => {
  return Promise.resolve({
    error: error.response
  });
});

await処理でajaxの結果を受け取る

awaitの処理で、上記でセットしたオブジェクトを受け取ります。

以下のように分割代入で受け取るとスッキリします。

const { data, error } = await ajax();
if (error) {
  // エラー時の処理
} else {
  // 正常時の処理
}

予期せぬエラーの場合(error.response.status = 500など)はエラー内容をthrowしたりする必要があるかもしれませんが、await処理ごとにエラー処理を実装できるようになりました。

もっと綺麗な方法が見つかるかもしれませんが、バリデーションエラーのような想定しておくべきエラーはcatchに飛ばさずに処理を実装したかったので、最終的にはこのような形になりました。


関連記事