はじめに
JavaScriptのAsync/Awaitについて初心者向けに理解を深める記事です。
awaitは確かに処理を「待つ」のですが、その関数の中だけで待つのであって、JavaScriptのメインスレッド全体をブロックするわけではありません。
同期処理との違い
// 同期処理の例(本当に全てが止まる)
function syncWait() {
const start = Date.now();
while (Date.now() - start < 2000) {
// 2秒間、何もできない状態
}
console.log("2秒経過");
}
console.log("開始");
syncWait(); // ここで本当に2秒間全てが止まる
console.log("終了");
// 出力:
// 開始
// (2秒間何もできない)
// 2秒経過
// 終了
// 非同期処理の例(Async/Await)
async function asyncWait() {
console.log("開始");
await new Promise(resolve => setTimeout(resolve, 2000));
console.log("2秒経過");
}
asyncWait();
console.log("終了"); // すぐに実行される
// 出力:
// 開始
// 終了 ← すぐに表示される
// (2秒後)
// 2秒経過
より実践的な例で理解しよう
async function fetchData() {
console.log("1. データ取得開始");
const data = await fetch("https://api.example.com/data");
console.log("3. データ取得完了");
return data;
}
console.log("A. プログラム開始");
fetchData();
console.log("B. 他の処理実行");
// 出力順序:
// A. プログラム開始
// 1. データ取得開始
// B. 他の処理実行 ← awaitで待っている間も実行される
// 3. データ取得完了
複数の非同期処理を同時実行
awaitは関数内で順番に待ちますが、複数のasync関数を並行実行することもできます。
async function task1() {
await new Promise(resolve => setTimeout(resolve, 2000));
return "タスク1完了";
}
async function task2() {
await new Promise(resolve => setTimeout(resolve, 2000));
return "タスク2完了";
}
// パターン1: 順番に実行(合計4秒)
async function sequential() {
console.log("開始");
const result1 = await task1(); // 2秒待つ
console.log(result1);
const result2 = await task2(); // さらに2秒待つ
console.log(result2);
console.log("終了");
}
// パターン2: 並行実行(合計2秒)
async function parallel() {
console.log("開始");
const [result1, result2] = await Promise.all([
task1(), // 同時に開始
task2() // 同時に開始
]);
console.log(result1);
console.log(result2);
console.log("終了");
}
まとめ
Async/Awaitの重要なポイントは以下の通りです。
-
awaitはasync関数の中でのみ処理を待つ - JavaScriptのメインスレッドは他の処理を続けられる
- 「非同期処理を同期的に書ける」シンタックスシュガーである
- 複数の処理を並行実行することも可能
つまり、「コードの見た目は同期的だが、実行は非同期」というのがAsync/Awaitの本質です。これにより、コールバック地獄を避けつつ、非同期処理のメリットを享受できるわけですね。