JavaScriptにおけるPromiseクラス
この記事ではJavaScriptにおけるPromiseクラスについて説明します。
YouTube Video
Promise
Promiseクラスは、非同期処理を扱うためのクラスです。処理が成功した場合の結果や、失敗した場合のエラーハンドリングを行います。非同期の処理が完了するまで待たないといけない場合には、コールバック関数を使うことが一般的でしたが、Promiseはそれをより分かりやすく、強力にしたものです。
1const promise = new Promise((resolve, reject) => {
2 setTimeout(() => resolve("Done!"), 1000);
3});
4
5// Displays "Done!" after 1 second
6promise.then(result => console.log(result));- このコードは、1秒後に "Done!" と表示する非同期処理を実行する例です。
- 最初に、
new Promiseによって新しくPromiseオブジェクトを作成しています。 引数には、成功時に呼ばれるresolveと失敗時に呼ばれるrejectの2つのコールバックを持つ関数を渡します。 setTimeoutを使って、1秒後にresolve()を呼び出しています。promiseオブジェクトのthen()メソッドによって、処理の完了を待ち、結果を表示しています。
- 最初に、
基本的な構造
Promiseは、最終的に成功と失敗の2つの結果を持つオブジェクトです。
1const promise = new Promise((resolve, reject) => {
2 // Asynchronous operation
3 // Flag indicating whether the operation was successful
4 const success = true;
5
6 if (success) {
7 resolve('Operation successful!');
8 } else {
9 reject('An error occurred');
10 }
11});- 成功の場合には、
resolve()を呼び出します。 - 失敗の場合には、
reject()を呼び出します。
Promiseオブジェクトは次の3つの状態を持っています。
1promise
2 .then((result) => {
3 console.log(result);
4 })
5 .catch((error) => {
6 console.error(error);
7 })- Pending(待機中)
- 非同期処理がまだ完了していない状態です。
- Fulfilled(成功)
- 非同期処理が成功し、
resolve()によって結果が返された状態です。then()メソッドによって結果を受け取ります。
- 非同期処理が成功し、
- Rejected(失敗)
- 非同期処理が失敗し、
reject()によってエラーが発生した状態です。catch()メソッドによってエラーを受け取ります。
- 非同期処理が失敗し、
then()とcatch()メソッド
Promiseを使うと、非同期処理が完了したときに行う処理を定義できます。これには、then()とcatch()メソッドを使います。
then()
1const promise = new Promise((resolve, reject) => {
2 resolve('Operation successful!');
3});
4
5promise.then((result) => {
6 console.log(result); // "Operation successful!"
7});then()メソッドは、Promiseが成功した場合に呼ばれる関数を指定します。
catch()
1const promise = new Promise((resolve, reject) => {
2 reject('An error occurred');
3});
4
5promise.catch((error) => {
6 console.error(error); // "An error occurred"
7});catch()メソッドは、Promiseが失敗した場合に呼ばれる関数を指定します。
finally()メソッド
1const promise = new Promise((resolve, reject) => {
2 resolve('Operation successful!');
3});
4
5promise
6 .then((result) => {
7 console.log(result);
8 })
9 .catch((error) => {
10 console.error(error);
11 })
12 .finally(() => {
13 console.log('The operation has completed');
14 });finally()メソッドは、Promiseが成功または失敗のいずれにしても、最終的に必ず実行されるコードを定義します。
then()チェーン
then()は新しいPromiseを返すので、次のthen()をチェーンできます。
1const promise = new Promise((resolve, reject) => {
2 setTimeout(() => {
3 resolve(1);
4 }, 1000);
5});
6
7promise
8 .then(result => {
9 console.log(result); // 1
10 return result + 1;
11 })
12 .then(result => {
13 console.log(result); // 2
14 return result + 1;
15 })
16 .then(result => {
17 console.log(result); // 3
18 })
19 .catch(error => {
20 console.error(error.message); // Something went wrong
21 });- このコードでは、最初の
resolve()で1が渡され、各thenで返した値は、次のthenに引き継がれます。 catch()を使うと、どこかのチェーンでエラーが発生したときにまとめて処理できます。
実際の例
例えば、サーバーからデータを取得するためにPromiseを使うことがよくあります。fetch() APIを使った例を見てみましょう。
1fetch('https://codesparklab.com/json/example.json')
2 .then(response => {
3 if (!response.ok) {
4 throw new Error('Network error');
5 }
6 return response.json();
7 })
8 .then(data => {
9 console.log(data);
10 })
11 .catch(error => {
12 console.error('Error:', error);
13 });- このコードでは、
fetch()がPromiseを返すので、サーバーからのレスポンスを受け取った後にデータを処理するためにthen()を使っています。エラーが発生した場合はcatch()で処理します。
複数のPromiseを扱う
Promise.all()
複数のPromiseを同時に実行し、それぞれが成功した場合のみ次の処理を行う場合、Promise.all()を使います。
1const promise1 = Promise.resolve(1);
2const promise2 = Promise.resolve(2);
3const promise3 = Promise.resolve(3);
4
5Promise.all([promise1, promise2, promise3])
6 .then((results) => {
7 console.log(results); // [1, 2, 3]
8 })
9 .catch((error) => {
10 console.error('Error :', error);
11 });- 全ての
Promiseが成功した場合のみthen()が呼ばれます。1つでも失敗すると、catch()が呼ばれます。
Promise.allSettled()
複数の Promise を同時に実行し、それぞれの成否に関係なくすべての結果を取得したい場合、Promise.allSettled() を使います。
1const promise1 = Promise.resolve(1);
2const promise2 = Promise.reject("Failed");
3const promise3 = Promise.resolve(3);
4
5Promise.allSettled([promise1, promise2, promise3])
6 .then((results) => {
7 results.forEach(result => console.log(result));
8 // [
9 // { status: 'fulfilled', value: 1 },
10 // { status: 'rejected', reason: 'Failed' },
11 // { status: 'fulfilled', value: 3 }
12 // ]
13 });- すべての
Promiseが完了(成功または失敗)した時点でthen()が呼ばれます。各結果にはstatusプロパティ('fulfilled'または'rejected')が含まれます。失敗しても他の処理には影響しません。
Promise.race()
Promise.race()は、最も早く解決された、つまり成功または失敗したPromiseの結果を取得します。
1const promise1 = new Promise((resolve) => setTimeout(resolve, 100, 'First'));
2const promise2 = new Promise((resolve) => setTimeout(resolve, 500, 'Second'));
3
4Promise.race([promise1, promise2]).then((result) => {
5 console.log(result); // "First"
6});- この例のように、最初に完了した
Promiseの結果が返されます。
async/awaitとの関係
async/await構文を使うことで、Promiseをより直感的に書くことができます。async関数は常にPromiseを返し、awaitはPromiseが解決するまで待機します。
1async function fetchData() {
2 try {
3 const response = await fetch('https://codesparklab.com/json/example.json');
4 const data = await response.json();
5 console.log(data);
6 } catch (error) {
7 console.error('Error :', error);
8 }
9}
10
11fetchData();このように、async/awaitを使うと、非同期処理が同期処理のように書けるため、コードが見やすくなります。
まとめ
Promiseは非同期処理の成功や失敗を扱うためのオブジェクトです。then()で成功時の処理、catch()でエラー時の処理を行います。finally()は成功や失敗に関わらず、最後に実行されるコードを定義します。Promise.all()やPromise.race()を使って、複数のPromiseをまとめて扱うことができます。async/awaitは、Promiseをよりシンプルに書くための構文です。
YouTubeチャンネルでは、Visual Studio Codeを用いて上記の記事を見ながら確認できます。 ぜひYouTubeチャンネルもご覧ください。