この記事では、非同期処理とは何か、またそれをうまく扱うためのPromiseという仕組みについて解説します。
非同期処理とは?
同期処理とは、ソースコードが上から順に一つずつ処理されることを指します。つまり、ある行の処理が完了するまで、次の行には進みません。これに対して非同期処理とは、ある行の処理が完了するのを待たずに次の行に進むことができる処理方法です。この非同期処理は、時間がかかる処理(例えば、大量のデータをフェッチする、大規模な計算を行う等)がある場合に特に有用です。
Promiseとは?
Promiseとは非同期処理の結果を扱うためのオブジェクトで、JavaScriptに組み込まれています。Promiseを利用すると、非同期処理が成功したときの処理と失敗したときの処理を簡潔に記述できます。
Promiseはresolve
とreject
という2つの関数を引数に取るコンストラクタで生成されます。resolve
関数は非同期処理が成功した場合に呼び出され、Promiseを「満たされた(fulfilled)」状態にします。一方、reject
関数は何らかの理由で非同期処理が失敗した場合に呼び出され、Promiseを「拒否された(rejected)」状態にします。それぞれの状態に応じて、後続の処理を.then()
メソッドや.catch()
メソッドで定義できます。
実際のコードを見てみよう
次の例は、非同期のAPIリクエストを模擬したコードです。
function apiCall(url) {
return new Promise( (resolve, reject) => {
setTimeout( () => {
if(url === 'https://api.example.com/data') {
resolve({ data: '成功しました!' });
} else {
reject('エラー:無効なURL');
}
}, 2000);
});
}
apiCall('https://api.example.com/data')
.then(response => console.log(response.data))
.catch(error => console.log(error));
apiCall('https://api.invalid.com')
.then(response => console.log(response.data))
.catch(error => console.log(error));
上記のapiCall
関数は、非同期のAPIリクエストをシミュレートしています。この関数はPromiseを返し、そのPromiseは2秒後に解決または拒否されます。解決の場合、resolve
関数が呼び出され、.then()
メソッドで定義した処理が実行されます。一方、拒否の場合、reject
関数が呼び出され、.catch()
メソッドで定義したエラーハンドリングが実行されます。
具体的な例とその結果を以下に示します。
成功した場合
上記のコードのうち、次の部分は有効なURLをapiCall
関数に渡し、Promiseが解決される例を示しています。
apiCall('https://api.example.com/data')
.then(response => console.log(response.data))
.catch(error => console.log(error));
このコードを実行すると、関数apiCall
は有効なURL(https://api.example.com/data
)を引数として受け取ります。その後、非同期処理が始まり、2秒後にresolve
関数が呼び出されます。resolve
関数は{ data: '成功しました!' }
というオブジェクトを引数として取り、このオブジェクトが次の.then()
メソッドに渡されます。.then()
メソッドの中で定義されている関数が実行され、コンソールに"成功しました!"と表示されます。
失敗した場合
次に、以下の部分は無効なURLをapiCall
関数に渡し、Promiseが拒否される例を示しています。
apiCall('https://api.invalid.com')
.then(response => console.log(response.data))
.catch(error => console.log(error));
このコードを実行すると、関数apiCall
は無効なURL(https://api.invalid.com
)を引数として受け取ります。その後、非同期処理が始まり、2秒後にreject
関数が呼び出されます。reject
関数は"エラー:無効なURL"という文字列を引数として取り、この文字列が次の.catch()
メソッドに渡されます。.catch()
メソッドの中で定義されている関数が実行され、コンソールに"エラー:無効なURL"と表示されます。
以上のように、Promiseのresolve
とreject
は、それぞれ非同期処理が成功したときと失敗したときの結果を次の処理に渡す役割を果たします。そして、.then()
と.catch()
メソッドを使用して、これらの結果をハンドリングします。
この例から、Promiseを使うと非同期処理が成功した場合と失敗した場合の両方に対応した処理を柔軟かつ簡潔に記述できることがわかります。
まとめ
非同期処理はJavaScriptで頻繁に扱われ、特にデータを扱うウェブアプリケーションでは必須の知識です。しかし、非同期処理は複雑になりがちで、コードの流れを理解しにくくなることがあります。Promiseを用いることで、この非同期処理の結果をうまく扱い、流れを制御することができます。これにより、より綺麗で理解しやすいコードを書くことが可能となります。