1. id が 1 の作品の要約が返る
  2. 表示回数が 0 の作品でも要約が返る
  3. 無い id を渡すと見つからない文が返る
  4. 空の配列を渡すと見つからない文が返る
コース一覧
非同期JavaScript:API通信とモジュール
async と await

非同期JavaScript:API通信とモジュール

Promise と async/await、非同期エラー、HTTP/REST、fetch による GET、読み込み・成功・失敗の表示、モジュールの読み方を学ぶ全 19 レッスン(380 分)のコースです。最後は承認済みの読み取り専用 API から作品データを取得して表示します。POST はリクエストの組み立てまでで、外部サービスへの書き込みは行いません。

1
非同期処理
01. 同期と非同期15分
02. Promise をつくって返す20分
03. async と await20分
04. Promise.all で同時に待つ20分
05. 非同期のエラーを捕まえる20分
06. つくる 読み込み中の表示を出す30分
07. 第1章まとめクイズ10分
2
fetch で外のデータを使う
01. HTTP と REST の読みかた15分
02. fetch でデータを取る25分
03. 取ったデータを描画する25分
04. response.ok と失敗時の表示25分
05. POST のリクエストを組み立てる20分
06. つくる 作品データを API から読む30分
07. 第2章まとめクイズ10分
3
モジュールと総仕上げ
01. ファイルを分けるという考えかた15分
02. named export と default export15分
03. つくる ポートフォリオアプリを仕上げる40分
04. ここから先の学びかた15分
05. 第3章まとめクイズ10分

async と await

await が止めるのはどこか
解説

このレッスンで分かること

  • await は中身が確定するまで、その関数だけを中断します
  • 前の結果を次に使いたいときは、await を縦に並べます

続きの処理が、どんどん奥へ押し込まれていく

.then に関数を渡す書き方には、ひとつ不便なところがあります。受け取った値を使う処理が、全部その関数の中に入ってしまうことです。届いた値をもとに次を取り、さらにその結果を使う、と続けるたびに、コードは奥へ奥へ沈んでいきます。

await を使うと、この沈み込みが消えます。中身が確定するまでその関数だけを中断し、確定したら続きから再開する、という書き方だからです。止まるのは関数の続きだけで、ページ全体は動いたままです。

JavaScript

async function showBadge() { const profile = await fetchProfile(); const badge = await fetchBadge(profile.level); console.log(badge.label); }

1 行目でプロフィールを取り、2 行目でその中の値を使ってバッジを取っています。2 行目は 1 行目の結果が無いと始められないので、順番に待つのが正しい書き方です。上から下へ読める形になるところが、await のいちばんのありがたみです。

await は async を付けた関数の中でしか書けません。付け方は関数の書き方ごとに次のとおりです。

書き方付ける場所
関数宣言async function showBadge() { }
関数式const showBadge = async function () { };
アロー関数const showBadge = async () => { };
イベントに渡す関数button.addEventListener("click", async function () { });

縦に並べた await は、待ち時間が足し算になる

前の結果を次に使うなら縦に並べるのが正しいのですが、互いに関係の無い 2 つを縦に並べると、待ち時間をむだに足しています。

JavaScript

// 100 ミリ秒 + 100 ミリ秒 で 200 ミリ秒かかる const profile = await fetchProfile(); const notice = await fetchNotice();

この 2 つは互いの結果を使っていないので、本当は同時に始めてよいはずです。並べる前に「前の結果を使うのか」を一度確かめる癖を付けておくと、無駄な待ちを見つけやすくなります。

無い値を、次の await に渡さない

早期 return は非同期でもそのまま使えます。むしろ非同期のほうが重要で、無い値を次の await に渡すと、追いにくいエラーになります。

JavaScript

async function showBadge() { const profile = await fetchProfile(); if (!profile.level) { return "バッジはまだありません"; } const badge = await fetchBadge(profile.level); return badge.label; }

profile.level が無いまま fetchBadge(undefined) を呼ぶと、箱の中で落ちます。await を挟んだ先で落ちたエラーは、どこから来たのか分かりにくいので、渡す前に止めるのが安全です。

解説

async を付けた関数から return した値は、そのまま返るのではなく Promise に包まれて返ります。上の関数は文字列を返していますが、呼ぶ側が受け取るのは「あとで文字列が入る箱」です。呼ぶ側でも await を書いてください。

よくある間違い

  • async を付け忘れて await を書く — 実行前に構文エラーになります。await is only valid in async functions のような文が出たら、外側の関数に async が付いているかを見てください
  • forEach の中で await を書く — forEach は、渡された関数が Promise を返しても待ちません。下のコードは中の await が終わる前に return へ進むので、空の配列が返ります。順番に待ちたいときは for-of を使ってください

JavaScript

async function collectLabels(profiles) { const labels = []; profiles.forEach(async function (profile) { const badge = await fetchBadge(profile.level); // 外側は待ってくれない labels.push(badge.label); }); return labels; // まだ空のまま返る }

要件

  1. fetchWorkList(works) を作る。60 ミリ秒後に works をそのまま resolve する Promise を返す
  2. fetchViews(work) を作る。60 ミリ秒後に work.views を resolve する Promise を返す
  3. loadWorkSummary(works, id) を async function として作り、一覧を await してから id の作品を探す
  4. 見つかったら「タイトル / 表示回数 回表示」の文字列を返す。見つからなければ fetchViews を呼ばずに「作品が見つかりません」を返す

入出力例

loadWorkSummary([{"id":1,"published":true,"title":"プロフィールサイト","views":120,"year":2026},{"id":2,"published":true,"title":"自己紹介カード","views":48,"year":2026},{"id":3,"published":true,"title":"スキル一覧の表","views":32,"year":2026},{"id":4,"published":true,"title":"作品ギャラリー","views":76,"year":2026},{"id":5,"published":false,"title":"学習ログ","views":0,"year":2025}], 1) → "プロフィールサイト / 120 回表示" loadWorkSummary([{"id":1,"published":true,"title":"プロフィールサイト","views":120,"year":2026},{"id":2,"published":true,"title":"自己紹介カード","views":48,"year":2026},{"id":3,"published":true,"title":"スキル一覧の表","views":32,"year":2026},{"id":4,"published":true,"title":"作品ギャラリー","views":76,"year":2026},{"id":5,"published":false,"title":"学習ログ","views":0,"year":2025}], 5) → "学習ログ / 0 回表示" loadWorkSummary([{"id":1,"published":true,"title":"プロフィールサイト","views":120,"year":2026},{"id":2,"published":true,"title":"自己紹介カード","views":48,"year":2026},{"id":3,"published":true,"title":"スキル一覧の表","views":32,"year":2026},{"id":4,"published":true,"title":"作品ギャラリー","views":76,"year":2026},{"id":5,"published":false,"title":"学習ログ","views":0,"year":2025}], 99) → "作品が見つかりません" loadWorkSummary([], 1) → "作品が見つかりません"

ヒント

await した戻り値には、resolve に渡した値がそのまま入ります。fetchWorkList の結果は配列なので、find で 1 件を探せます

見つからなかったときは fetchViews を呼ばずに return してください。undefined を渡すと Promise の中で落ちます

文字列は「タイトル / 表示回数 回表示」の形です。スラッシュの前後に半角スペースが 1 つずつ入ります

生田 陸人
監修生田 陸人
ゆめさくエンジニア / 現役ソフトウェアエンジニア監修者プロフィールを見る →
編集 ゆめさく編集部·公開 2026/03/27·更新 2026/08/26

関連レッスン

  • Promise.all で同時に待つ

    互いに関係の無い非同期処理をまとめて始め、全部そろうまで 1 回だけ待ちます。待ち時間の合計が、いちばん遅い 1 つぶんまで縮みます。

  • 非同期のエラーを捕まえる

    reject された Promise は await した行で例外になります。第6章の try と catch をそのまま使って受け止め、失敗しても同じ形の値を返します。

  • つくる 読み込み中の表示を出す

    300 ミリ秒遅れて届く Promise を自作し、待っているあいだのスピナーと、届いたあとのカード表示を切り替えます。第9章で通信につなぐ前の下ごしらえです。

  • 第1章まとめクイズ

    Promise の確定、await の書き忘れ、forEach の中の await、Promise.all の並び順、reject の受け止め方を、コードを読んで確かめます。

このレッスンに出てくる用語

意味があいまいなまま進んだ語は、ここから読み直せます。

  • 関数処理に名前を付けて再利用できる単位
  • 処理計算や代入を表す長方形
  • アロー関数=> で書く軽量な関数。this を継承する
  • イベントユーザーの操作(クリック、入力、スクロール等)を検知して処理を実行する仕組み。
  • 非同期完了を待たずに次へ進み、後で結果を受ける
  • 同期処理が終わるまで次に進まない実行順
  • Promise非同期の結果を表すラッパーオブジェクト
  • 配列サイズ固定の同型データの集まり
main.js
学習モード
エディタを読み込んでいます

メモ

async と await

⌘S で保存