1. ホーム
  2. 記事一覧
  3. JavaScriptの基礎 async/awaitを理解しよう

2024.09.26

JavaScriptの基礎 async/awaitを理解しよう

はじめに

非同期処理を扱う方法はJavaScriptにいくつかありますが、今ではasync/awaitが主流となっています。 async/awaitは、Promiseよりもシンプルで、コードの見通しが良くなる という利点があります。ただ、使い方に慣れていないと難しく感じることもあるでしょう。「Promiseとどう違うの?」「どっちを使えばいいの?」と疑問に思う方もいるかもしれません。

この記事では、そういった疑問を解消するために、async/awaitの仕組みやそのメリット、Promiseとの違いを詳しく解説します。**async/awaitをしっかり理解することで、非同期処理の扱い方がスムーズになり、コード記述がしやすくなります。**非同期処理を扱うことは現在のWeb開発に必須のスキルとなりますので、一緒に学んでいきましょう!

この記事について

目的

  • async/awaitを理解する
  • Promiseとの違いを知る
  • async/awaitを使用してデータ操作ができるようになる

対象者

  • 初学者の方
  • JavaScriptの勉強を最近始めた方

JavaScriptの基本について

この記事ではJavaScriptの基本的な説明には触れていません。JavaScriptの基礎や実践ハンズオンを以下の記事で紹介していますので、理解を深めたい方はぜひご覧ください。

https://envader.plus/article/331

async/awaitについて

JavaScriptにおけるasync/awaitとは、非同期処理でデータを取得する際に使用される関数です。asyncは関数の前に付けることで、その関数が非同期処理を行うことを宣言します。この関数は必ずPromiseを返します。

非同期処理とは、ある処理が終わるのを待たずに次の処理に進む動作のことを指します。サーバーからデータを取得するなど、時間のかかる処理を待っている間も、他のプログラムが進行できる仕組みです。

async関数の中では、awaitという構文を使って、非同期処理が終わるまで一時停止することができます。awaitは、Promiseが解決(成功)または拒否(失敗)されるまで待ちます。通常、非同期処理では、その処理が完了する前に次の行のコードが実行されますが、awaitを使うと、その処理が終わるまで次の処理を待つようになります。asyncとawaitは、通常セットで使用します。awaitはasync関数の中でしか使えないため、非同期処理を扱うときは、この二つを一緒に使うのが一般的です。

このように、async/awaitを使うことで、非同期処理を順序通りに書けるため、コードの可読性が向上し処理の流れが理解しやすくなります。

async/awaitが導入された背景

async/awaitは、非同期処理で使用するコールバック関数やPromiseよりも、コードの可読性と管理をしやすくするために導入された構文です。async/awaitはPromiseをベースにしており、基本的には同じ目的で使用しますが、コードの可読性と記述のしやすさに重点を置いて設計されています。

非同期処理を実現するために、最初はコールバック関数が使われていました。コールバック関数では、非同期処理が終わった後に実行される関数を渡します。しかし、処理が複雑化するとコードのネストが深くなる「コールバック地獄」と呼ばれる現象が発生し、コードの可読性が低下し管理が難しくなります。この問題を解決するためにPromiseが導入されました。しかし、非同期処理が連続したり、複数のPromiseを組み合わせるなど、処理が複雑化するとPromiseでの管理も難しくなることがあります。

そこで、コールバック関数やPromiseの課題を解決するためにasync/awaitが登場しました。async/awaitはコードのネストを避け、シンプルに記述できるのが特徴です。その直感的で分かりやすい手法により、Pythonなど他の言語でも採用されています。

async/awaitとPromiseの使い分け

非同期処理にはいくつかの書き方がありますが、実際の開発ではどれを使えば良いのか悩む方もいるかもしれません。私自身も、複雑でない処理ならPromiseでも十分では?と疑問に思ったことがあります。

現在、非同期処理の記述ではasync/awaitが主流です。async/awaitはPromiseの発展型として導入されており、非同期処理の流れや管理がしやすく、多くの開発現場で採用されています。これら2つをどう使い分けるかは、コードの複雑さや実行したい処理に応じて選択すると良いでしょう。

たとえば、コードの可読性を上げたい場合や、非同期処理を順番に実行したい場合はasync/awaitが適しています。一方で、シンプルな処理や複数の非同期処理を並行して実行したい場合には、Promiseが有効です。このように、処理内容に応じて使い分けるのが良いかと思います。

なお、Promiseも非同期処理の基本を支える概念であり、async/awaitもその背後ではPromiseを利用しているため、どちらも仕組みを理解しておく必要があります。

Promiseについては以下の記事で詳しく解説していますので、ぜひご覧ください。

https://envader.plus/article/468

async/awaitの使い方

async/awaitの基本について学びました。async/awaitは「コードの可読性と管理をしやすくするために導入された構文」と学びましたが、実際にどのように記述するか、Promiseでの処理との違いをコード例とあわせて確認しましょう。

以下のコードは、async/awaitの基本的な使い方を示しています。これを使うことで、JavaScriptの非同期処理を簡単に書くことができます。

// 関数名にasyncをつけてasyncで非同期処理をする
async function asyncFunc() {
  return 'async-値';
}
// asyncFunc関数はPromiseを返す
asyncFunc().then((value) => {
  console.log(value); // => 'async-値'
});

コードの解説

// 関数名にasyncをつけてasyncで非同期処理をする
async function asyncFunc() {
  return 'async-値';
}

async を使って関数を定義しています。この async キーワードを関数の前につけると、その関数は必ず Promise を返すようになります。関数内で何か値を返した場合、その値は自動的に Promise.resolve() で包まれ、Promise オブジェクトとして扱われます。

// asyncFunc関数はPromiseを返す
asyncFunc().then((value) => {
  console.log(value); // => 'async-値'
});

asyncFunc().then() メソッドを使うことで、非同期処理が完了したときの値を受け取ることができます。この場合、then((value) => {...}) の部分では、Promise が完了すると、その結果である 'async-値'value に渡されます。その後、この value は次の処理である console.log() に渡され、出力結果として 'async-値' が表示されます。

このコードを通じて理解しておきたいポイント

async を使うと、関数の処理結果が自動的に Promise になるため、明示的に作成する必要がなくなります。通常の Promise では以下のように、Promise.resolve()Promise.reject() を使ってPromiseを作成し、その結果を処理しますが、asyncを使えばこれを省略できます。

たとえば、Promiseを使った場合は次のように書かなければいけません。

function promiseFunc() {
  return Promise.resolve('値');
}

promiseFunc().then((value) => {
  console.log(value);
});

一方、asyncを使うと次のようにシンプルになります。

async function asyncFunc() {
  return '値';
}

asyncFunc().then((value) => {
  console.log(value);
});

このように、asyncを使うことで Promise.resolve() を自分で書かなくても、関数内で単に return すればその値が自動的に Promiseでラップされます。この例のコードはシンプルなため、asyncの効果をさほど感じないかもしれませが、コードが複雑になるにつれ、非同期処理を扱う際の手間が減り、コードが読みやすくなることを実感できるかと思います。

async/awaitを使ってみよう

これまでに、async/awaitの基本的な使い方やコードの書き方を学びました。このセクションでは、実際にasync/awaitを使ってコードを書き、ハンズオン形式で理解を深めていきましょう。今回は、POSTメソッドを使用してサーバーにデータを送信します。

今回のハンズオンでは、JSONPlaceholderというAPIサービスを利用します。JSONPlaceholderは、開発者がAPIを使ってデータのやり取りを練習できる、無料のオンラインモックAPIサービスです。

また、ブラウザ上で直接コードを試したい方には、以下のサイトをおすすめします。フロントエンドの環境構築が不要で、すぐにasync/awaitのコードを実行できます。

async/awaitを使用したデータのPOSTメソッドの送信

今回のハンズオンでは以下のファイルを編集し、POSTメソッドを使用してJSONPlaceholderへデータを送信します。

  • index.html
  • main.js

index.htmlの内容は以下の通りです。ここで、main.jsファイルを読み込みます。

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>asyncAwait</title>
  </head>
  <body>
    <div id="app"></div>
    <script type="module" src="/main.js"></script>
  </body>
</html>

次に、main.jsでasync/awaitを使ってデータを送信するコードを書きます。非同期処理を行い、サーバーへPOSTメソッドを使用してデータを送信する関数を定義します。

// main.js

// async関数を使ってデータをPOSTメソッドで送信
async function postData() {
  const url = 'https://jsonplaceholder.typicode.com/posts'; // JSONPlaceholderのPOSTエンドポイント
  const data = {
    title: 'エンベーダー',
    body: 'エンジニア予備軍のためのITインフラ学習ゲーム',
    userId: 1,
  };

  try {
    const response = await fetch(url, {
      method: 'POST', // HTTPメソッドをPOSTに指定
      headers: {
        'Content-Type': 'application/json', // 送信データの形式を指定
      },
      body: JSON.stringify(data), // JavaScriptオブジェクトをJSON形式に変換して送信
    });

    const result = await response.json(); // サーバーからの応答をJSONとして取得
    console.log('送信内容:', result); // 結果を表示
  } catch (error) {
    console.error('エラーが発生しました:', error); // エラーハンドリング
  }
}

// 関数を実行
postData();

コードを編集後、index.htmlをブラウザで開き、開発者ツールのConsoleを確認します。以下のように送信内容がConsoleに表示がされていれば、POST送信が成功したことになります。

コードの解説

今回のハンズオンではasync/awaitのPOSTメソッドを使用して、JSONPlaceholderへデータを送信しました。コードを1つずつ確認していきましょう。

  • async関数の作成と送信先、値の定義

    // async関数を使ってデータをPOSTメソッドで送信
    async function postData() {
      const url = 'https://jsonplaceholder.typicode.com/posts'; // JSONPlaceholderのPOSTエンドポイント
      const data = {
        title: 'エンベーダー',
        body: 'エンジニア予備軍のためのITインフラ学習ゲーム',
        userId: 1,
      };

    async関数を作成し、データの送信先と値を定義しています。値のキーはJSONPlaceholderで説明されているものを使用しています。

    キーや値、メソッドの解説は以下のページで確認していただけます。

    https://jsonplaceholder.typicode.com/guide/

  • メソッドを指定してAPIへデータ送信

      try {
        const response = await fetch(url, {
          method: 'POST', // HTTPメソッドをPOSTに指定
          headers: {
            'Content-Type': 'application/json', // 送信データの形式を指定
          },
          body: JSON.stringify(data), // JavaScriptオブジェクトをJSON形式に変換して送信
        });
    
        const result = await response.json(); // サーバーからの応答をJSONとして取得
        console.log('送信内容:', result); // 結果を表示
      } catch (error) {
        console.error('エラーが発生しました:', error); // エラーハンドリング
      }
    }
    • メソッドと送信データ形式の指定

      POST メソッドを指定し、fetch関数を使用しサーバーへデータを送信します。headers: 内で送信するデータはJSON形式ということを{ 'Content-Type': 'application/json' }で指定しています。サーバーは通常、JSON形式でデータを受け取るため、body: JSON.stringify(data)で値をJSON形式に変換します。

    • awaitの定義

      const result = await response.json();部分では、awaitを使って fetch 処理の完了を待ちます。処理完了後は、結果を response 変数に代入し、次の処理へ渡します。

    • try構文

      エラーが発生する可能性がある処理を実行し、そのエラーを安全に処理するために使われます。もし try ブロック内の処理でエラーが発生した場合、そのエラーをcatchして対応することができます。

このハンズオンでは、async/awaitを使って非同期処理を整理し、APIへデータを送信する流れを学ぶことができます。コードの可読性と管理をしやすくするために導入された構文ということを感じていただけるかと思います。async/awaitを使うことで、非同期処理を簡単に記述し管理できることがわかりました。

この記事で学んだこと

JavaScriptにおけるasync/awaitは、非同期処理を簡潔かつ直感的に記述するための構文です。従来使用されていたコールバック関数やPromiseに比べて、async/awaitはコードの可読性が高く、記述がシンプルになるよう設計されています。

現在、多くの開発現場で非同期処理の記述方法としてasync/awaitが主流となっています。async/awaitは、Promiseを基盤にしつつ、非同期処理の流れや管理を容易にするため、複雑な処理でも効率的に扱えます。どちらを使うかは、コードの複雑さや実行したい処理に応じて適切に選択すると良いでしょう。

参考資料

【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

IT未経験者必見 USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話

プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。

「フリーランスエンジニア」

近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。

「成功する人とそうでない人の違いは何か?」

私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。

比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。

多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、

note記事3000いいね超えの殿堂記事 今すぐ読む

エンベーダー編集部

エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。

RareTECH 無料体験授業開催中! オンラインにて実施中! Top10%のエンジニアになる秘訣を伝授します! RareTECH講師への質疑応答可

関連記事