8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptの非同期処理とイベントループ

Posted at

JavaScriptの非同期処理とイベントループ

コールスタック

  • コールスタックは「いまどの関数が動いていて、その中でどの関数を呼び出したのか」を管理する仕組みです
  • スタック構造なので、最後に呼ばれた関数から順番に処理が戻っていきます

シングルスレッド

  • JavaScriptはシングルスレッドで動作し、同時に複数の処理を並列に実行できません
  • ただし、ブラウザはWeb APIという仕組みを持ち、通信処理やタイマー処理などをバックグラウンドで進めてくれます

例: setTimeoutfetch はWeb APIに処理を依頼し、完了後にコールバックキューへ戻されます。
その後、イベントループにより順番が来たときに再びスタックへ積まれて実行されます。

イベントループの流れ(図解)

┌───────────────┐
│ Call Stack │ ← 関数が実行される場所
└───────┬───────┘


┌───────────────┐
│ Web API │ ← setTimeout / fetch などが動く
└───────┬───────┘


┌───────────────┐
│ Callback Queue │ ← 完了した処理が待機する場所
└───────┬───────┘


┌───────────────┐
│ Event Loop │ ← Stack が空なら Queue から実行
└───────┬───────┘


(再び Call Stack へ)

コールバック地獄

  • 非同期処理をコールバック関数でネストしまくると、可読性が落ちます
  • これをコールバック地獄と呼びます
doTask1((result1) => {
  doTask2(result1, (result2) => {
    doTask3(result2, (result3) => {
      console.log("すべて完了:", result3);
    });
  });
});

見ての通り、ネストが深くなると大変です。

Promise(約束)

  • Promiseは「非同期処理の最終的な成功または失敗」を表すオブジェクトです

  • 状態は以下の3つ:

    • pending(待機中): 初期状態
    • fulfilled(成功): 処理が完了
    • rejected(失敗): 処理がエラーで終了
mockRequest("api/data/page1")
  .then((res1) => {
    console.log("ページ1成功:", res1);
    return mockRequest("api/data/page2");
  })
  .then((res2) => {
    console.log("ページ2成功:", res2);
    return mockRequest("api/data/page3");
  })
  .then((res3) => {
    console.log("ページ3成功:", res3);
  })
  .catch((err) => {
    console.error("エラー発生:", err);
  });

Promiseを使うことで、ネストが浅くなり見通し良くなります。

async / await

  • async関数は必ずPromiseを返す特殊な関数です

    • 値を返せば、自動的にPromise.resolve(value)になる
    • エラーを投げれば、Promise.reject(error)になる
  • awaitはPromiseが解決するまで処理を一時停止し、結果を直接受け取れます

async function fetchData() {
  try {
    const data1 = await mockRequest("api/info/step1");
    console.log("step1:", data1);

    const data2 = await mockRequest("api/info/step2");
    console.log("step2:", data2);

    const data3 = await mockRequest("api/info/step3");
    console.log("step3:", data3);

  } catch (err) {
    console.error("処理に失敗:", err);
  }
}

これで同期処理のように書けるため、可読性が大幅に向上します。

8
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?