my.code(); Logomy.code();
JavaScript-9.非同期処理②: Async/Await

my.code(); Logomy.code();

  • C++
    • 0.C++の世界へようこそ
    • 1.型システムと制御構造
    • 2.データ集合とモダンな操作
    • 3.ポインタとメモリ管理
    • 4.関数と参照渡し
    • 5.プロジェクトの分割とビルド
    • 6.クラスの基礎
    • 7.クラスを使いこなす
    • 8.継承とポリモーフィズム
    • 9.テンプレート
    • 10.STL ①:コンテナ
    • 11.STL ②:アルゴリズムとラムダ式
    • 12.RAIIとスマートポインタ
  • JavaScript
    • 0.JavaScriptへようこそ
    • 1.基本構文とデータ型
    • 2.制御構文
    • 3.関数とクロージャ
    • 4.'this'の正体
    • 5.オブジェクトとプロトタイプ
    • 6.クラス構文
    • 7.配列とイテレーション
    • 8.非同期処理①: Promise
    • 9.非同期処理②: Async/Await
  • Python
    • 0.環境構築と基本思想
    • 1.基本構文とデータ型
    • 2.リスト、タプル、辞書、セット
    • 3.制御構文と関数
    • 4.モジュールとパッケージ
    • 5.オブジェクト指向プログラミング
    • 6.ファイルの入出力とコンテキストマネージャ
    • 7.例外処理
    • 8.ジェネレータとデコレータ
  • Ruby
    • 0.rubyの世界へようこそ
    • 1.基本構文とデータ型
    • 2.制御構造とメソッド定義
    • 3.すべてがオブジェクト
    • 4.コレクション (Array, Hash, Range)
    • 5.ブロックとイテレータ
    • 6.クラスとオブジェクト
    • 7.モジュールとMix-in
    • 8.Proc, Lambda, クロージャ
    • 9.標準ライブラリの活用
    • 10.テスト文化入門
    • 11.メタプログラミング入門
  • Rust
    • 0.Rustの世界へようこそ
    • 1.基本構文と「不変性」
    • 2.関数と制御フロー
    • 3.所有権
    • 4.借用とスライス
    • 5.構造体とメソッド構文
    • 6.列挙型とパターンマッチ
    • 7.モジュールシステムとパッケージ管理
    • 8.コレクションと文字列
    • 9.エラーハンドリング
    • 10.ジェネリクスとトレイト
    • 11.ライフタイム
  • TypeScript
    • 0.TypeScriptへようこそ
    • 1.基本的な型と型推論
    • 2.オブジェクト、インターフェース、型エイリアス
    • 3.関数の型定義
    • 4.型を組み合わせる
    • 5.ジェネリクス
    • 6.クラスとアクセス修飾子
    • 7.非同期処理とユーティリティ型
my.code(); Logomy.code();

環境構築不要、その場で実践。

ut-code / my-code

Copyright © 2026 ut.code();

ut.code(); について
公式ウェブサイト公式 𝕏 アカウント
my.code(); について
コード実行環境についてAI質問機能についてライセンスお問い合わせ

第9章: 非同期処理(2)- Async/Await と Fetch API

前回(第9章)では、JavaScriptの非同期処理の要である Promise について学びました。しかし、.then() チェーンが長く続くと、コードの可読性が下がる(いわゆる「コールバック地獄」に近い状態になる)ことがあります。

第10章では、この課題を解決するために導入された Async/Await 構文と、現代的なHTTP通信の標準である Fetch API について解説します。他の言語で同期的なコード(ブロッキング処理)に慣れ親しんだ方にとって、Async/Await は非常に直感的で扱いやすい機能です。

Async/Await 構文

async と await は、ES2017で導入された Promise のシンタックスシュガー(糖衣構文)です。これを使うことで、非同期処理をあたかも「同期処理」のように上から下へと流れるコードとして記述できます。

async 関数

関数宣言の前に async キーワードを付けると、その関数は自動的に Promiseを返す ようになります。値を return した場合、それは Promise.resolve(値) と同じ意味になります。

JavaScript 実行環境
ブラウザ上で動作するJavaScriptのREPL実行環境です。
プロンプト (>) の後にコマンドを入力し、Enterキーで実行します。
Ctrl+Cまたは左上の停止ボタンで実行中のコマンドを中断できます。
> async function getMessage() { return "Hello, Async!"; }
undefined
> // async関数は常にPromiseを返す
> getMessage()
Promise { 'Hello, Async!' }

> // 通常のPromiseと同じくthenで値を取り出せる
> getMessage().then(v => console.log(v))
Promise { <pending> }
Hello, Async!

await 式

async 関数の内部(またはモジュールのトップレベル)でのみ使用できるキーワードです。 await は、右側の Promise が Settled(解決または拒否)されるまで関数の実行を一時停止 します。Promiseが解決されると、その結果の値を返して実行を再開します。

これは、C# の async/await や Python の asyncio に慣れている方にはおなじみの挙動でしょう。

JavaScript 実行環境
ブラウザ上で動作するJavaScriptのREPL実行環境です。
プロンプト (>) の後にコマンドを入力し、Enterキーで実行します。
Ctrl+Cまたは左上の停止ボタンで実行中のコマンドを中断できます。
> function delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)); }
undefined
> async function run() {
...   console.log("Start");
...   await delay(1000); // 1秒待機(ここで実行が一時停止)
...   console.log("End");
... }
undefined
> run()
Promise { <pending> }
// (1秒後に表示)
Start
End

try...catch によるエラーハンドリング

生の Promise では .catch() メソッドを使ってエラーを処理しましたが、Async/Await では、他の言語と同様に標準的な try...catch 構文を使用できます。これにより、同期エラーと非同期エラーを同じ構文で扱えるようになります。

ファイルを編集:async_try_catch.js
// ランダムに成功・失敗する非同期関数
function randomRequest() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            const success = Math.random() > 0.5;
            if (success) {
                resolve("Success: データ取得完了");
            } else {
                reject(new Error("Failure: サーバーエラー"));
            }
        }, 500);
    });
}

async function main() {
    console.log("処理開始...");
    try {
        // awaitしているPromiseがrejectされると、例外がスローされる
        const result = await randomRequest();
        console.log(result);
    } catch (error) {
        // ここでエラーを捕捉
        console.error("エラーが発生しました:", error.message);
    } finally {
        console.log("処理終了");
    }
}

main();
node async_try_catch.js
ブラウザ上で動作するJavaScriptの実行環境です。
左上の実行ボタンを押して、このページ内のasync_try_catch.jsに書かれている内容を実行します。
処理開始...
エラーが発生しました: Failure: サーバーエラー
処理終了

(※注: 実行結果はランダムで成功する場合もあります)

Fetch API によるHTTPリクエスト

JavaScript(特にブラウザ環境や最近のNode.js)でHTTPリクエストを行うための標準APIが fetch です。以前は XMLHttpRequest という扱いづらいAPIが使われていましたが、現在は fetch が主流です。

fetch 関数は Promise を返します。

基本的な流れは以下の通りです:

  1. fetch(url) を実行し、レスポンスヘッダーが届くのを待つ。
  2. Responseオブジェクトを受け取る。
  3. Responseオブジェクトからメソッド(.json(), .text()など)を使ってボディを読み込む(これも非同期)。
ファイルを編集:fetch_basic.js
// 外部APIからJSONデータを取得する例
// (Node.js 18以上ではfetchが標準で使用可能です)

async function getUserData(userId) {
    const url = `https://jsonplaceholder.typicode.com/users/${userId}`;

    try {
        // 1. リクエスト送信 (ネットワークエラー以外はrejectされない)
        const response = await fetch(url);

        // 2. HTTPステータスコードの確認
        if (!response.ok) {
            throw new Error(`HTTP Error: ${response.status}`);
        }

        // 3. レスポンスボディをJSONとしてパース (これもPromiseを返す)
        const data = await response.json();
        
        console.log(`Name: ${data.name}`);
        console.log(`Email: ${data.email}`);

    } catch (error) {
        console.error("Fetch failed:", error.message);
    }
}

getUserData(1);
node fetch_basic.js
ブラウザ上で動作するJavaScriptの実行環境です。
左上の実行ボタンを押して、このページ内のfetch_basic.jsに書かれている内容を実行します。
Name: Leanne Graham
Email: Sincere@april.biz

JSONデータの送信 (POST)

データを送信する場合は、第2引数にオプションオブジェクトを渡します。

JavaScript 実行環境
ブラウザ上で動作するJavaScriptのREPL実行環境です。
プロンプト (>) の後にコマンドを入力し、Enterキーで実行します。
Ctrl+Cまたは左上の停止ボタンで実行中のコマンドを中断できます。
> const postData = { title: 'foo', body: 'bar', userId: 1 };
> await fetch('https://jsonplaceholder.typicode.com/posts', {
...   method: 'POST',
...   headers: { 'Content-Type': 'application/json' },
...   body: JSON.stringify(postData)
... }).then(res => res.json())
{ title: 'foo', body: 'bar', userId: 1, id: 101 }

Promise.all() と Promise.race()

Async/Await は便利ですが、単純に await を連発すると、処理が直列(シーケンシャル)になってしまい、パフォーマンスが落ちる場合があります。複数の独立した非同期処理を行う場合は、並列実行を検討します。

直列実行(遅いパターン)

// Aが終わってからBを開始する
const user = await fetchUser(); 
const posts = await fetchPosts(); 

Promise.all() による並列実行

複数のPromiseを配列として受け取り、全て完了するのを待ってから結果の配列を返します。一つでも失敗すると全体が失敗(reject)します。

ファイルを編集:promise_all.js
const wait = (ms, value) => new Promise(r => setTimeout(() => r(value), ms));

async function parallelDemo() {
    console.time("Total Time");

    // 2つの処理を同時に開始
    const p1 = wait(1000, "User Data");
    const p2 = wait(1000, "Post Data");

    try {
        // 両方の完了を待つ
        const [user, post] = await Promise.all([p1, p2]);
        console.log("Result:", user, "&", post);
    } catch (e) {
        console.error(e);
    }

    // 本来なら直列だと2秒かかるが、並列なので約1秒で終わる
    console.timeEnd("Total Time");
}

parallelDemo();
node promise_all.js
ブラウザ上で動作するJavaScriptの実行環境です。
左上の実行ボタンを押して、このページ内のpromise_all.jsに書かれている内容を実行します。
Result: User Data & Post Data
Total Time: 1.008s

Promise.race()

複数のPromiseのうち、最も早く完了(または失敗)したものの結果だけを返します。タイムアウト処理の実装などによく使われます。

JavaScript 実行環境
ブラウザ上で動作するJavaScriptのREPL実行環境です。
プロンプト (>) の後にコマンドを入力し、Enterキーで実行します。
Ctrl+Cまたは左上の停止ボタンで実行中のコマンドを中断できます。
> const fast = new Promise(r => setTimeout(() => r("Fast"), 100));
> const slow = new Promise(r => setTimeout(() => r("Slow"), 500));
> await Promise.race([fast, slow])
'Fast'

この章のまとめ

  • Async/Await: Promise をベースにした糖衣構文。非同期処理を同期処理のように記述でき、可読性が高い。
  • Error Handling: 同期コードと同じく try...catch が使用可能。
  • Fetch API: モダンなHTTP通信API。response.ok でステータスを確認し、response.json() でボディをパースする2段構えが必要。
  • 並列処理: 独立した複数の非同期処理は await を連続させるのではなく、Promise.all() を使用して並列化することでパフォーマンスを向上させる。

練習問題1: ユーザー情報の取得と表示

以下の要件を満たす関数 displayUserSummary(userId) を作成してください。

  1. https://jsonplaceholder.typicode.com/users/{userId} からユーザー情報を取得する。
  2. https://jsonplaceholder.typicode.com/users/{userId}/todos からそのユーザーのTODOリストを取得する。
  3. 上記2つのリクエストは、パフォーマンスを考慮して並列に実行すること。
  4. 取得したデータから、「ユーザー名」と「完了済み(completed: true)のTODOの数」を出力する。
  5. 通信エラー時は適切にエラーメッセージを表示する。
ファイルを編集:practice10_1.js
node practice10_1.js
ブラウザ上で動作するJavaScriptの実行環境です。
左上の実行ボタンを押して、このページ内のpractice10_1.jsに書かれている内容を実行します。

練習問題2: タイムアウト付きFetch

指定したURLからデータを取得するが、一定時間内にレスポンスが返ってこない場合は「タイムアウト」としてエラーにする関数 fetchWithTimeout(url, ms) を作成してください。 ヒント: fetch のPromiseと、指定時間後に reject するPromiseを Promise.race() で競走させてください。

ファイルを編集:practice10_2.js
node practice10_2.js
ブラウザ上で動作するJavaScriptの実行環境です。
左上の実行ボタンを押して、このページ内のpractice10_2.jsに書かれている内容を実行します。
前のページ« 非同期処理①: Promise