【JavaScript入門】Promiseの基本
処理の流れ

※ https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Promise より画像引用
Promise(プロミス)
「将来的に必ず何らかの結果(成功または失敗)になることが約束されている値」を表すオブジェクトのことを指します。
Promise を生成するには、コンストラクタ( new Promise() )を使用し、その中にエグゼキュータ関数(Executor Function)と呼ばれる関数を渡すのが基本です。
エグゼキュータ関数は、JavaScriptによって引数として自動的に2つのコールバック関数を受け取ります。
-
resolve
非同期処理が成功したときに呼び出す関数 -
reject
非同期処理が失敗したときに呼び出す関数
Promiseコンストラクタ内で非同期処理を定義し、その結果に応じて resolve または reject を呼び出すことで、非同期処理の状態を管理し、後続の .then() や .catch() へとその状態を伝えることができます。
Promise の3つの状態
Pending(保留)
処理がまだ進行中
Fulfilled(成功)
- 処理が成功して完了した状態
- resolve() が呼び出された後の状態
Rejected(失敗)
- 処理が失敗して完了した状態
- reject() が呼び出された後の状態
※「Fulfilled」または「Rejected」のどちらかの状態になったことを総称して 「Settled」(確定済み)と呼びます。
Promise の受け取り方(使い方)
1. コールバック形式: .then() と .catch()
非同期処理が完了するのを待って、その結果(成功または失敗)に応じて処理を記述する方法です。
askQuestion('名前は?')
.then((result) => {
// 成功したとき(resolveが呼ばれたとき)に実行される
console.log(`入力された名前: ${result}`);
})
.catch((error) => {
// 失敗したとき(rejectが呼ばれたとき)に実行される
console.error(`エラーが発生しました: ${error}`);
});
// Promiseは非同期なので、then() の中の処理を待たずに以下の行が先に実行される
console.log('質問はしたけど、回答を待たずに次の行の処理は進むよ');
2. 同期形式: async/await
Promise を返す関数の結果を、あたかも同期処理のように(順番に)待ちながら受け取る方法です。
async function main() { // awaitを使う関数は async をつける
try {
// askQuestion が完了して結果(answer)が返ってくるまで、ここで処理を停止(待機)する
const name = await askQuestion('名前は?');
console.log(`入力された名前: ${name}`);
const age = await askQuestion('年齢は?');
console.log(`入力された年齢: ${age}`);
} catch (error) {
console.error(`エラーが発生しました: ${error}`);
}
}
main(); // async 関数を実行する
Promise の生成と利用の基本的な流れ
1. Promise の作成(生成)
非同期処理(rl.question など)を Promise コンストラクタでラップし、結果が出たときに resolve または reject を呼び出します。
// askQuestion の中身
return new Promise((resolve) => {
// 非同期処理を開始
rl.question('質問文', (answer) => {
// 非同期処理が成功したとき
resolve(answer);
});
// 失敗の可能性がないため reject は省略
});
resolve() は、非同期処理が完了し、成功裏に結果が得られたときに、そのコールバック関数の内部で呼び出されます。
resolve() の役割は値を運ぶことであり、その値を使って何をするかは Promise の外側で記述します。
2. Promise の利用
async function run() {
// resolve(answer) で運ばれてきた値が foodAnswer に代入されるまで待機する
const foodAnswer = await askQuestion('好きな食べ物は?');
// 成功したい処理、つまり値を利用したい処理をここに記述する
console.log(`${foodAnswer} がお好きなんですね!`);
}
resolve() の2つの役割
-
状態の変更
resolve() が呼び出されると、その Promise オブジェクトの状態が Pending(保留中) から Fulfilled(成功/完了) へと変化します。この状態変化は元に戻せません。 -
結果の伝達
resolve(value) のように引数として渡された valueを、その Promise を待っている側のコード(.then() のコールバックや await の左辺の変数)に結果として引き渡します。
まとめ
- Promise は将来結果を受け取ることが約束されたオブジェクト
- Promise は状態を管理している(Pending, Fulfilled, Rejected)
| 関数 | 役割 | Promiseの状態変化 |
|---|---|---|
| resolve(value) | 非同期処理の成功を通知し、結果の値を渡す | Pending → Fulfilled (成功) |
| reject(reason) | 非同期処理の失敗を通知し、エラー情報を渡す | Pending → Rejected (失敗) |
参考URL
Discussion