async/awaitで非同期処理をスッキリ書く方法|実務で使えるJavaScriptコード例

async/awaitで非同期処理をスッキリ書く方法 業務効率化

こんな悩みはありませんか

APIからデータを取得する処理を書いていて、.then().then().then()とPromiseが連なっていくコードを見て「読みにくいな」と感じたことはないでしょうか。あるいは、非同期処理の順番がうまくいかず、データが取れる前に次の処理が走ってしまってエラーになった経験がある方も多いはずです。

非同期処理はJavaScriptを使う以上避けて通れないテーマですが、async/awaitを使うと、処理の流れを上から下へ順番に読めるコードとして書けるようになります。

この記事でできるようになること

この記事を読むと、async/awaitの基本的な書き方から、実務でよくある「複数のAPIを順番に呼ぶ」「複数の処理を並行して実行する」「エラーハンドリングをきちんと書く」といったパターンまで、手を動かしながら理解できるようになります。

async/awaitは特別な仕組みではなく、Promiseを読みやすく書くための構文だと理解しておくと、学習の負担がぐっと減ります。

async/awaitの基本を押さえる

asyncキーワードで関数を非同期にする

関数の前にasyncをつけると、その関数は自動的にPromiseを返すようになります。

async function fetchUser() {
  return "ユーザー情報";
}

fetchUser().then((result) => console.log(result));

asyncをつけただけの関数でも、戻り値は自動的にPromiseでラップされます。ここはまず「そういうものだ」と受け止めてもらえれば大丈夫です。

awaitで処理の完了を待つ

awaitは、Promiseの結果が返ってくるまで処理を一時停止させるキーワードです。async関数の中でしか使えない点に注意してください。

async function getUserData() {
  const response = await fetch("https://api.example.com/user");
  const data = await response.json();
  console.log(data);
}

上から下に読むだけで処理の順番がわかるので、.then()を重ねるより格段に見通しがよくなります。

実務で使えるコード例

複数のAPIを順番に呼び出す

ユーザー情報を取得したあと、そのIDを使って注文履歴を取得する、といった処理は実務でもよくあります。

async function getOrderHistory() {
  const user = await fetchUser();
  const orders = await fetchOrders(user.id);
  return orders;
}

複数の処理を並行して実行する

互いに依存しない処理をawaitで順番に書いてしまうと、無駄に時間がかかります。こういうときはPromise.allと組み合わせるのがおすすめです。

async function getDashboardData() {
  const [user, notifications, tasks] = await Promise.all([
    fetchUser(),
    fetchNotifications(),
    fetchTasks(),
  ]);
  return { user, notifications, tasks };
}

個人的には、この「並行化できる処理はないか」を意識するだけで、体感速度がかなり変わると感じています。

try/catchでエラーハンドリングする

async/awaitではエラー処理をtry/catchで書けます。これは.then().catch()より直感的です。

async function safeFetchUser() {
  try {
    const response = await fetch("https://api.example.com/user");
    if (!response.ok) {
      throw new Error("通信に失敗しました");
    }
    return await response.json();
  } catch (error) {
    console.error("エラーが発生しました:", error.message);
    return null;
  }
}

ポイント:async関数の中でエラーが発生する可能性がある処理は、必ずtry/catchで囲んでおきましょう。囲まないと、エラーが握りつぶされたまま気づきにくくなります。

つまずきやすいポイントと対処

awaitを忘れる

最初は戸惑いやすいポイントですが、Promiseを返す処理にawaitをつけ忘れると、結果ではなくPromiseオブジェクトそのものが変数に入ってしまいます。コンソールにPromise { <pending> }と表示されたら、まずここを疑ってみてください。

forEachの中でawaitが効かない

forEachのコールバック内でawaitを書いても、順番通りに待ってくれません。ここは正直つまずく方が多い部分です。順番に処理したい場合はfor...ofを使いましょう。

for (const id of userIds) {
  const user = await fetchUser(id);
  console.log(user);
}

配列の各要素を並行処理したいだけなら、mapで作ったPromiseの配列をPromise.allに渡す方法もあります。用途に応じて使い分けるとよいでしょう。

エラーハンドリングを省略してしまう

動作確認中はエラーが出ないため、ついtry/catchを後回しにしてしまいがちです。しかし本番環境では通信エラーやAPIの仕様変更など、想定外のことが必ず起こります。非同期処理を書いたら、エラー処理までセットで書く習慣をつけておくと、後々のトラブルをかなり減らせます。

注意:async関数内でthrowしたエラーは、呼び出し側でtry/catchするかPromiseの.catch()で受け取らないと、未処理のエラーとして扱われてしまいます。

まとめ

async/awaitは、非同期処理を同期処理のように読みやすく書くための構文です。基本のasyncawaitの使い方さえ押さえれば、あとはPromise.allによる並行処理とtry/catchによるエラーハンドリングを組み合わせるだけで、実務のほとんどのケースに対応できます。

まずは自分が普段書いているコールバックやPromiseのコードを、ひとつでもいいのでasync/awaitに書き換えてみてはいかがでしょうか。実際に手を動かすことで、理解の定着が早まるはずです。

PR

AIサブスクの月額がかさんできたら

複数のAIサービスを1つの契約にまとめて、コストを抑えながら使い倒す選択肢もあります。

月額料金を賢く集約。複数のAIサブスクを1つにまとめて、最高峰の知能を使い倒すならDoraverse。

コメント

タイトルとURLをコピーしました