非同期処理って何?Promise/async/awaitやデータ取得の方法について解説します!【JavaScript】
JavaScriptを学習していると「非同期処理」という言葉を聞いたことはありませんか?
この記事は「非同期処理とは何かイマイチ分からない」「非同期処理を使って、アプリ開発したい!」という方に
読んでいただきたい記事になっています。
この記事を読み終えると、非同期処理とは何か、非同期関数の実行方法などを一通り知った状態になるでしょう。
目次:
この記事のポイント
- 非同期処理が何かがわかる
- Promiseととは何かがわかる
- then/catch/finallyとは何かがわかる
- async/awaitとは何かがわかる
- try/catch/finallyとは何かがわかる
- 実際のAPIサービスからデータ取得の仕方がわかる
そもそも非同期処理とは?なぜ必要?
JavaScriptはシングルスレッドで動作する言語です。
そのため、1つの処理が完了するまで他の処理を待つ必要があり、他の処理が行えなくなります。
ここで登場するのが「非同期処理」です。
非同期処理を使うと、時間のかかる処理が完了するのを待つ間、他の処理を進めることができます。
例えば、サーバーからのデータ取得やファイルの読み込みなどは時間がかかる可能性が高いため、
これを非同期で行うことで、他の処理をブロックすることなくプログラムを効率的に動かすことができます。
Promiseって何?基本的な使い方を解説
非同期処理の基本的な構文の1つがPromiseです。
Promiseは「約束」を意味し、処理の結果が「成功」か「失敗」かを表現するものです。
以下のように、Promiseは3つの状態を持ちます。
Promiseの3つの状態:
- Pending(保留中):処理がまだ完了していない状態
- Fulfilled(成功):処理が成功し、結果が得られた状態
- Rejected(失敗):処理が失敗した状態
例:基本のPromiseの構文
// 実行されると必ず成功する記述
new Promise((resolve, reject) => {
resolve();
});
// 実行されると必ず失敗する記述
const func = new Promise((resolve, reject) => {
reject();
});
// 実行方法
func
.then(() => {})
.catch(() => {})
例:簡単なPromiseの構文
const promise = new Promise((resolve, reject) => {
// 非同期処理を記述
let success = true; // 成功を仮定
if (success) {
resolve('成功しました!');
} else {
reject('失敗しました。');
}
});
// 非同期関数を実行
promise
.then(result => console.log(result)) // 成功時の処理
.catch(error => console.log(error)); // 失敗時の処理
.finally(() => console.log('最終処理');); // 必ず実行される処理
この例では、「成功しました!」という結果が出力されます。
関連: then、catch、finallyとは?
thenとcatchは非同期処理が完了後のタイミングで動作し、
thenは成功した際、catchは失敗した際に実行されます。
これらを使うと、APIとの通信が成功した場合のみある処理をして、失敗した際はエラーを表示するなどが可能になります。
finallyは上記2つより使用頻度は下がりますが、
失敗/成功に関わらず必ず実行したい処理を記述できます。
async/awaitでPromiseをもっとシンプルに
Promiseを使った非同期処理は強力ですが、thenやcatchを連続して書くとコードが複雑に見えることもあります。
これがthenやcatchを使うことのデメリットです。
例:複雑で読みにくい非同期処理コード
promise1
.then(response => response.json()) // 最初のAPIリクエストでユーザーデータを取得
.then(user => {
console.log('ユーザー情報:', user);
return promise2;
})
.then(response => response.json()) // 次のPromiseの結果を処理
.then(posts => {
console.log('ユーザーの投稿:', posts);
})
.catch(error => {
console.error('エラーが発生しました:', error); // すべてのPromiseのエラーをここでキャッチ
});
ここで、解決策としてasync/awaitが登場します。
async/awaitを使うと、非同期処理をまるで同期処理のように記述できるので、コードがシンプルで読みやすくなります。
例:簡単なasync/await構文
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
console.log(data);
} catch (error) {
console.log('エラーが発生しました:', error);
} finally {
console.log('必ず実行');
}
}
fetchData();
この例では、fetchメソッドでデータを取得し、そのデータを処理するまで待機(await)することができます。
thenとcatchは非同期処理が完了後のタイミングで動作し、
thenは成功した際、catchは失敗した際に実行されます。
これらを使うと、APIとの通信が成功した場合のみある処理をして、失敗した際はエラーを表示するなどが可能になります。
finallyは上記2つより使用頻度は下がりますが、
失敗/成功に関わらず必ず実行したい処理を記述できます。
関連: try、catch、finallyとは?
どちらもエラーハンドリングをするという点では同じですが、
then/catchとは動作が若干違うので、混同しないよう注意しましょう。
then/catchは非同期処理のエラーハンドリングを行うのに対し、
try/catchは同期処理全般 (awaitを使い同期的にしたものも含む)のエラーハンドリングをします。
tryは、エラーが発生する可能性のあるコードを囲む部分です。
try内でエラーが発生すると、コードの実行は中断され、すぐに catchブロックへ制御が移ります。
catchでエラーをキャッチし任意の処理ができます。
finallyはエラーが発生してもしなくても必ず実行したい処理を書けます。
非同期データ取得の実例:APIからデータを取得してみよう!
実際に非同期処理を使ってAPIからデータを取得する例を見てみましょう。
例:fetchを使ったAPIからのデータ取得
async function getData() {
try {
const response = await fetch('https://jsonplaceholder.typicode.com/posts');
const data = await response.json();
console.log(data);
} catch (error) {
console.error('データ取得に失敗しました:', error);
}
}
getData();
このコードは、APIからデータを取得し、そのデータをコンソールに表示します。
fetchは非同期なAPIリクエストを行うためのブラウザの組み込み関数で、awaitを使ってレスポンスを待つことができます。
もしエラーが発生した場合、catchブロックでエラーメッセージを表示します。
非同期処理のメリットと注意点
非同期処理を使うことで、時間のかかる処理が完了するまで他の処理を止めることなく実行できます。
しかし、非同期処理はその特性上、デバッグが難しくなったり、コードの実行順序がわかりにくくなったりする可能性があります。
そのため、try/catchやasync/awaitをうまく使って、読みやすくメンテナンスしやすいコードを書くことが重要です。
まとめ
いかがだったでしょうか?
初学者の場合、非同期処理を理解することは、一度では難しいかもしれません。
しかし、JavaScriptでアプリの開発をする場合は頻繁に登場するため、マスターすることは必須級です。
理解できるまで復習して使いこなせるようになりましょう。
また、関連知識としてtry/catchなどもご紹介しました。
エラーハンドリングもよく行うことなので、この記事だけで理解できない場合、他の記事も参考にしてください。
CodeVilageでは無料カウンセリングを実施しております!
「興味はあるけど、自分にできるか不安...」
「どんなキャリアを描けばいいのか分からない...」
そんなあなたのために!!
何でも相談できる無料カウンセリングを実施しています。