JavaScriptのPromiseとは?非同期処理の基本をわかりやすく解説

JavaScriptのPromiseによる非同期処理の流れとデータのつながりを表現した抽象イメージ
JavaScriptのPromiseを活用した非同期処理の仕組みとデータフローを視覚的に表現したイメージ

JavaScriptにおける非同期処理は、Web制作において非常に重要な概念です。
その中心的な役割を担うのが「Promise」です。

この記事では、Promiseの基本から使い方、よくあるパターンまでを、基礎から理解できるように解説します。

Promiseとは何か

Promiseとは、非同期処理の結果を「あとで受け取る」ための仕組みです。

通常の処理(同期処理)は、上から順番に実行されますが、非同期処理では「完了を待たずに次へ進む」という特徴があります。

たとえば以下のような処理です。

  • API通信
  • ファイル読み込み
  • タイマー処理(setTimeout)

これらは処理に時間がかかるため、完了を待たずに次の処理が進みます。

Promiseが必要な理由

従来のJavaScriptでは、非同期処理は「コールバック関数」で扱われていました。

しかし、コールバックを多用すると、以下のような問題が発生します。

  • ネストが深くなる(コールバック地獄)
  • 可読性が低下する
  • エラーハンドリングが複雑になる

この問題を解決するために登場したのがPromiseです。

👉 関連記事:

Promiseの基本構造

Promiseは以下のように作成します。

const promise = new Promise((resolve, reject) => {
  // 非同期処理を書く
});

Promiseには3つの状態があります。

  • pending(待機中)
  • fulfilled(成功)
  • rejected(失敗)

resolveとrejectの役割

Promiseの中では、処理の結果に応じて以下を使います。

  • resolve:成功したとき
  • reject:失敗したとき
const promise = new Promise((resolve, reject) => {
  const success = true;

  if (success) {
    resolve("成功しました");
  } else {
    reject("失敗しました");
  }
});

thenとcatchの使い方

Promiseの結果は、thencatchで受け取ります。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("処理が完了しました");
  }, 1000);
});

promise
  .then((result) => {
    console.log(result);
  })
  .catch((error) => {
    console.log(error);
  });

Promiseの流れを理解する

Promiseは次のような流れで動きます。

  1. Promiseを作成
  2. 非同期処理を実行
  3. 成功ならresolve
  4. 失敗ならreject
  5. then/catchで結果を受け取る

thenチェーンで処理をつなげる

Promiseはthenをつなげることで、処理を連続して書くことができます。

const promise = new Promise((resolve) => {
  resolve(1);
});

promise
  .then((value) => {
    console.log(value); // 1
    return value + 1;
  })
  .then((value) => {
    console.log(value); // 2
    return value + 1;
  })
  .then((value) => {
    console.log(value); // 3
  });

Promise.allの使い方

複数の非同期処理を同時に実行したい場合は、Promise.allを使います。

const promise1 = Promise.resolve("A");
const promise2 = Promise.resolve("B");
const promise3 = Promise.resolve("C");

Promise.all([promise1, promise2, promise3])
  .then((results) => {
    console.log(results); // ["A", "B", "C"]
  })
  .catch((error) => {
    console.log(error);
  });

Promise.raceの使い方

最初に完了したPromiseの結果だけを取得する場合は、Promise.raceを使います。

const promise1 = new Promise((resolve) => {
  setTimeout(() => resolve("1秒"), 1000);
});

const promise2 = new Promise((resolve) => {
  setTimeout(() => resolve("2秒"), 2000);
});

Promise.race([promise1, promise2])
  .then((result) => {
    console.log(result); // "1秒"
  });

async/awaitとの関係

Promiseは、async/awaitと組み合わせて使うことが多いです。

async/awaitを使うと、非同期処理を同期的に書けます。

function wait(ms) {
  return new Promise((resolve) => {
    setTimeout(resolve, ms);
  });
}

async function main() {
  await wait(1000);
  console.log("1秒経過");
}

main();

👉 関連記事:

Promiseを使うときの注意点

returnを忘れない

thenの中でPromiseを返さないと、チェーンが正しく動きません。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(1);
  }, 1000);
});

promise
  .then((value) => {
    return value + 1;
  })
  .then((value) => {
    console.log(value);
  })
  .catch((error) => {
    console.error(error);
  });

エラーハンドリングは必ず行う

catchを使ってエラーを処理することが重要です。

const promise = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("成功");
  }, 1000);
});

promise
  .then((value) => {
    console.log(value);
  })
  .catch((error) => {
    console.error("エラー:", error);
  });

Promiseを理解するためのポイント

Promiseを理解するうえで重要なのは次の3つです。

  • 非同期処理の結果を扱う仕組みである
  • 状態(pending / fulfilled / rejected)を持つ
  • then / catchで結果を処理する

まとめ

Promiseは、JavaScriptの非同期処理を扱うための基本機能です。

コールバックに比べてコードが整理され、読みやすくなります。

さらに、async/awaitと組み合わせることで、より直感的なコードを書くことが可能になります。

関連記事