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チャンネルもご覧ください。