JavaScriptのPromiseとは、すぐには終わらない処理の結果を、あとで受け取るための仕組みです。
Promiseが分かると、fetch、then、catch、async/await のコードを「何を待って、どこで結果を受け取るのか」という流れで読めるようになります。

Promiseは「結果そのもの」ではなく、「あとで結果を受け取る入口」です。最初はこの理解だけで十分です。
この記事では、Promiseの意味、3つの状態、then・catch・finallyの使い方、fetchでつまずきやすいポイント、async/awaitとの関係を順番に解説します。
まず結論:Promiseは将来の結果を表すオブジェクト
Promiseは、非同期処理の最終的な成功または失敗を表すオブジェクトです。MDNでも、Promiseは非同期処理の完了または失敗と、その結果の値を表すものとして説明されています。
ただし、初心者のうちは仕様文を暗記するより、次の読み方を先に覚える方が実用的です。
非同期処理を始める
↓
Promiseが返る
↓
成功したら then
失敗したら catch
最後に finally
この時点で大事なのは、Promiseが返ってきても、まだ中身の結果を直接持っているとは限らないことです。結果はあとから成功または失敗として確定します。
Promiseが必要になる場面
JavaScriptでは、通信、タイマー、ファイル読み込みのように、すぐ終わらない処理がよく出てきます。特にWebアプリでは、APIからデータを取るfetchが代表例です。
通信が終わるまで画面全体を止めると、ユーザーは操作できません。そのためJavaScriptでは、通信を待っている間も他の処理を進め、結果が返ってきたときに続きを実行します。
この「あとで続きを実行する」ための約束を整理するのがPromiseです。
Promiseの流れを図で見る
次の図では、Promiseを「非同期処理の結果を、成功・失敗・最後の処理へ分けて受け取る流れ」として見てください。細かい用語より先に、左から右への読み順を作るのがポイントです。

pending・fulfilled・rejectedの3状態
Promiseには状態があります。まずは次の3つだけ押さえれば十分です。
| 状態 | 意味 | 初心者向けの見方 |
|---|---|---|
| pending | まだ結果が出ていない | 処理中 |
| fulfilled | 成功して結果が得られた | 成功 |
| rejected | 失敗して理由が返った | 失敗 |
Promiseは最初にpendingになり、その後、成功すればfulfilled、失敗すればrejectedになります。成功と失敗のどちらかに決まった状態を、実務では「settled」と表現することもあります。
then・catch・finallyの役割
Promiseでよく使うのは、then、catch、finallyです。
| メソッド | 役割 | よくある使い方 |
|---|---|---|
then() | 成功時の結果を受け取る | 取得したデータを画面に出す |
catch() | 失敗時の理由を受け取る | エラー表示やログ出力をする |
finally() | 成功・失敗に関係なく最後に動く | ローディング表示を消す |
fetch("/api/users")
.then((response) => response.json())
.then((users) => {
console.log(users);
})
.catch((error) => {
console.error("取得に失敗しました", error);
})
.finally(() => {
console.log("読み込み処理を終了します");
});
ポイントは、前のthenで返した値が、次のthenへ渡されることです。response.json()を返すから、次のthenで変換後のデータを受け取れます。
fetchでよくある誤解:HTTPエラーは必ずcatchに入るわけではない
Promiseをfetchで使うとき、初心者がつまずきやすいのがエラー処理です。ネットワーク自体に失敗した場合はcatchに入りますが、HTTPステータスが404や500の場合は、必ずしも自動でcatchに入るとは限りません。
fetchの結果では、response.okを見て、HTTPとして成功扱いできるかを確認するのが安全です。
fetch("/api/users")
.then((response) => {
if (!response.ok) {
throw new Error("HTTPエラー: " + response.status);
}
return response.json();
})
.then((users) => {
console.log(users);
})
.catch((error) => {
console.error(error);
});
このように書くと、通信そのものの失敗だけでなく、サーバーがエラーを返した場合も同じcatchで扱いやすくなります。
async/awaitはPromiseを読みやすくする書き方
async/awaitは、Promiseと別物ではありません。Promiseを、上から順に読む形で書きやすくするための構文です。
async function loadUsers() {
try {
const response = await fetch("/api/users");
if (!response.ok) {
throw new Error("HTTPエラー: " + response.status);
}
const users = await response.json();
console.log(users);
} catch (error) {
console.error(error);
}
}
awaitはPromiseの完了を待ち、その結果を取り出します。つまり、async/awaitを使っていても、裏側ではPromiseを扱っています。
最初に覚える判断基準
Promise.allは最初から暗記しなくてよい
Promiseを調べると、Promise.all、Promise.race、Promise.allSettledなども出てきます。これらは複数のPromiseをまとめて扱うための機能です。
ただし、初学者が最初に全部を覚える必要はありません。まずは、1つのPromiseが成功・失敗へ分かれる流れを読めることが先です。複数の通信を同時に待つ必要が出てきたときに、Promise.allを学ぶ順番で問題ありません。
たとえば、ユーザー情報と注文履歴を同時に取得したい場合は、複数のPromiseをまとめて待つ考え方が必要になります。一方、単に1つのAPIからデータを取るだけなら、then・catch・finallyとasync/awaitを理解していれば十分です。
コードレビューで見るポイント
Promiseを使ったコードを読むときは、まず「どこでPromiseが作られ、どこで結果を取り出しているか」を見ます。次に、失敗時の処理があるか、ローディング表示などの後片付けが漏れていないかを確認します。
特にWeb画面では、通信中の表示、成功時の表示、失敗時の表示がそろっているかが重要です。Promiseの文法だけでなく、ユーザーに何が見えるかまで考えると、実務のコードを読みやすくなります。
公式情報と関連して読みたい記事
まとめ
Promiseは、非同期処理の結果をあとで受け取るための仕組みです。最初は「将来の結果を表すオブジェクト」と考えれば十分です。
