JavaScriptにおける「Promise API」は、非同期処理を管理するための強力な機能です。この技術は、従来のコールバック関数(callback)を使った非同期処理の複雑さを解消し、コードをより直感的で理解しやすいものにします。この記事では、Promise APIの基本的な概念から、実際の使用方法、エラーハンドリング、チェーン、さらにはasync/awaitとの関係について詳細に解説します。
1. Promiseの基本概念
Promiseは、非同期操作が完了したときの結果を表現するオブジェクトです。Promiseは以下の3つの状態を持ちます:
-
待機中(pending): Promiseが非同期処理を実行している最中。この状態では、まだ結果が返されていません。
-
解決済み(fulfilled): 非同期処理が成功し、結果が返された状態。
-
拒否済み(rejected): 非同期処理が失敗し、エラーが発生した状態。
Promiseは、以下のように作成できます:
javascriptconst promise = new Promise((resolve, reject) => {
// 非同期操作のコード
});
上記のコードでは、resolveとrejectという2つの関数が提供されます。非同期処理が成功した場合はresolveを呼び出し、失敗した場合はrejectを呼び出します。
2. Promiseの利用方法
Promiseを使用すると、非同期処理の結果に対する処理を簡単に定義できます。thenメソッドとcatchメソッドを使うことで、成功時と失敗時の処理を定義します。
javascriptconst promise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("成功しました");
} else {
reject("エラーが発生しました");
}
});
promise
.then((result) => {
console.log(result); // "成功しました"
})
.catch((error) => {
console.log(error); // "エラーが発生しました"
});
3. Promiseチェーン
thenメソッドは、非同期処理が成功した場合に返される値を次のthenメソッドに渡すことができます。これにより、複数の非同期操作を順番に処理することができます。このプロセスをPromiseチェーンと呼びます。
javascriptconst promise = new Promise((resolve, reject) => {
resolve("最初の処理");
});
promise
.then((result) => {
console.log(result); // "最初の処理"
return "次の処理";
})
.then((result) => {
console.log(result); // "次の処理"
})
.catch((error) => {
console.log(error);
});
4. Promiseのエラーハンドリング
Promiseのエラーハンドリングは、catchメソッドを使用して行います。catchはPromiseチェーンの中でエラーが発生した場合に処理を行います。例えば、非同期処理中に発生したエラーを捕えるためには次のようにします。
javascriptconst promise = new Promise((resolve, reject) => {
throw new Error("予期しないエラー");
});
promise
.then((result) => {
console.log(result);
})
.catch((error) => {
console.error("エラーが発生しました:", error.message); // "エラーが発生しました: 予期しないエラー"
});
5. Promise.allとPromise.race
複数のPromiseを並行して実行する場合、Promise.allとPromise.raceが非常に便利です。
-
Promise.all: 配列内のすべてのPromiseが成功するまで待機し、すべての結果を一度に返します。いずれかのPromiseが失敗すると、即座に失敗として返されます。
javascriptconst promise1 = new Promise((resolve) => setTimeout(resolve, 1000, "結果1"));
const promise2 = new Promise((resolve) => setTimeout(resolve, 2000, "結果2"));
Promise.all([promise1, promise2])
.then((results) => {
console.log(results); // ["結果1", "結果2"]
})
.catch((error) => {
console.error(error);
});
-
Promise.race: 最初に解決または拒否されたPromiseの結果を返します。
javascriptconst promise1 = new Promise((resolve) => setTimeout(resolve, 1000, "結果1"));
const promise2 = new Promise((resolve) => setTimeout(resolve, 2000, "結果2"));
Promise.race([promise1, promise2])
.then((result) => {
console.log(result); // "結果1"
})
.catch((error) => {
console.error(error);
});
6. async / awaitとPromise
async / awaitは、Promiseを使った非同期処理をより直感的に記述するための構文です。async関数内ではawaitを使ってPromiseの解決を待つことができます。これにより、非同期処理が同期的なコードのように見えます。
javascriptasync function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log(data);
} catch (error) {
console.error("エラーが発生しました:", error);
}
}
fetchData();
awaitはPromiseの解決を待つため、Promiseが解決するまで次の行に進まないことに注意してください。これにより、非同期処理の順序が保たれます。
7. Promiseの適用例
実際のアプリケーションでは、APIの呼び出しやファイルの読み込み、タイマー処理など、さまざまな非同期処理でPromiseを活用できます。例えば、非同期にデータを取得し、画面に表示するコードは次のように書けます。
javascriptasync function getUserData(userId) {
try {
const response = await fetch(`https://api.example.com/user/${userId}`);
const data = await response.json();
console.log(data);
} catch (error) {
console.error("ユーザーデータの取得に失敗しました:", error);
}
}
getUserData(123);
まとめ
JavaScriptのPromise APIは、非同期処理を効率的に扱うための強力なツールです。then、catch、finallyメソッドを使ったチェーン処理や、Promise.allやPromise.raceを使った複数のPromiseの管理、さらにasync/awaitを使ったシンプルで直感的な非同期処理の記述方法を学ぶことで、非同期プログラミングがより簡単に、そして効果的に行えるようになります。非同期処理が増える現代のJavaScriptにおいて、Promiseは欠かせない技術となっています。
