
【JavaScript入門】asyncとawait
async / await は ES2017 で導入された “Promise を同期処理のように書く” シンタックスシュガーです。長い .then() チェーンをフラットに書き直し、可読性 と 例外処理の一貫性 を大幅に高めます。ここでは構文の概要と使いどころを表・実践コードで整理し、最後に try … catch によるエラー制御も確認します。

1.async / await の基礎
| 概念 | 説明 |
|---|---|
async 関数 | 頭に async を付けた関数。戻り値は暗黙に Promise になる。 |
await 式 | Promise が 解決 (fulfilled) されるまで次の行へ進まない(直列化) |
| エラー伝播 | await で reject() や throw が起きると 例外 が発生し、try … catch で捕捉できる。 |
1.1. async が付くと何が変わるか
- 明示的に Promise を返さなくても 自動で Promise 化
- 関数外では
func().then()やawait func()で結果を取得
1.2. await の動作
- 右辺が Promise なら解決値を取り出す。
- 右辺が値(非 Promise)なら即時にその値を返す。
awaitはasync関数内でのみ有効
1.3. エラー処理の統一
Promise チェーンの .catch() と同じ役目を try … catch に集約できるため、同期コードと同じスタイルで書ける。
2.基本サンプル
ファイル名:async-await-demo.html
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8" />
<title>⚡️ async / await デモ</title>
<style>
body {font-family: "Segoe UI", sans-serif; margin: 2rem; background: #f0f8ff;}
h1 {font-size: 1.8rem; text-align: center; margin-bottom: 1rem;}
#log {white-space: pre-line; border: 1px solid #ccc; border-radius: 8px;
padding: 1rem; background: #fff; min-height: 8rem;}
button {padding: .6rem 1.2rem; border: none; border-radius: 6px;
background: #0078d7; color: #fff; font-weight: bold; cursor: pointer;}
button:hover {opacity: .85;}
</style>
</head>
<body>
<h1>⚡️ async / await デモ</h1>
<button id="runBtn">非同期タスク開始</button>
<div id="log"></div>
<script>
// 指定ミリ秒後に解決 / 拒否する Promise
const waitTask = (label, ok = true, ms = 150) =>
new Promise((resolve, reject) =>
setTimeout(() => ok ? resolve(`${label} 完了`) : reject(`${label} 失敗`), ms)
);
const log = txt => document.getElementById("log").textContent += txt + "\n";
// async 関数
async function runFlow() {
log("=== フロー開始 ===");
log(await waitTask("タスクA")); // 直列に実行
log(await waitTask("タスクB"));
log("--- 中間地点 ---");
const c = await waitTask("タスクC");
const d = await waitTask("タスクD");
log(c);
log(d);
log("=== フロー終了 ===");
}
document.getElementById("runBtn").onclick = () => {
document.getElementById("log").textContent = ""; // ログクリア
runFlow().catch(e => log("予期せぬエラー: " + e));
};
</script>
</body>
</html>ブラウザの出力例

プログラム解説
waitTaskはテスト用の非同期関数。ok=falseにするとreject()を呼ぶ。awaitで直列化 — Promise が解決するまで次の行に進まないため、上から下へ順序どおりにログが出る。- 関数外 (
onclick部分) ではrunFlow()が Promise を返すので.catch()で安全に例外を拾える。
3.try … catch と await
3.1. エラーを握りつぶさず取得する
ファイル名: async-await-try-catch.html
<!-- async-await-try-catch.html (抜粋) -->
<script>
async function runWithError() {
log("▼ エラー実験 ▼");
try {
log(await waitTask("ステップ1"));
log(await waitTask("ステップ2", false)); // ← ここで reject
log(await waitTask("ステップ3")); // 実行されない
} catch (e) {
log("例外捕捉: " + e); // reject がここへ飛ぶ
} finally {
log("▲ エラー実験終了 ▲");
}
}
</script>ブラウザの出力例

プログラム解説
await に失敗すると同期コードの throw と同じように catch 節へジャンプします。UI のローディング解除は finally に書くと安心です。
4.ベストプラクティス
- ループ + 並列処理 が欲しい場合は
awaitをループ外に出しPromise.all()を組み合わせる。 - 共通エラーハンドリング は関数の外で
.catch()、局所的なハンドリングはtry … catch。 - トップレベルの
awaitはモジュール (<script type="module">) か(async () => {/*…*/})()で利用。
まとめ
async / await により、複雑だった Promise チェーンを 同期的な読みやすさ で書けるようになります。await を使えば変数代入や try … catch に馴染みのある制御フローが戻ってきます。まずは小さな非同期関数を async に書き換え、処理の追いやすさ・バグの検出しやすさを体感してみましょう。
