こんにちは、ラーメン好きなフリーランスエンジニアの”ぽんねぐ”です。
JavaScriptを学び始めると、すぐに「非同期処理」という言葉に出会います。APIからデータを取得したり、タイマーを使ったりする際に使われる技術ですが、初心者には少し難しく感じるかもしれません。
そんな非同期処理をシンプルに書くために登場したのが、async / await
です。本記事では、基本的な使い方を、初心者にもわかりやすい用語解説付きで解説していきます!
本記事を最後まで読んで頂くことで以下のようなお悩みを解決できます。
以下の関連記事についても一緒にご確認頂けるとJavaScriptのことがもっと理解できます。
まずは簡単に私のことを紹介します。
それでは始めていきましょう。
async / awaitとは?
非同期処理とは?
非同期処理とは、簡単に言うと「時間のかかる処理を待つ間に、他の作業を続けられるプログラミングの仕組み」です。
例えば次のようなケースです:
- サーバーからデータを取得する(APIコール)
- 画像や動画などの大きなファイルをダウンロードする
- タイマーで一定時間後に何かを実行する
通常のコードでは、これらの処理が終わるまで待つ必要がありますが、非同期処理を使うと、プログラムが「他の仕事」を先に進めることができます。
asyncとは?
async
は「非同期関数」を作るためのキーワードです。このキーワードをつけた関数は、常にPromise
という特別なオブジェクトを返します。
例:async関数の基本
async function greet() {
return "Hello, World!";
}
greet().then(message => console.log(message)); // "Hello, World!"
上記の例では、async
関数の戻り値は自動的にPromise
になります。つまり、関数がすぐに結果を返さず、「そのうち結果を渡すよ」と約束する形になります。
awaitとは?
await
は、非同期処理の結果が返ってくるまで待機するキーワードです。ただし、await
はasync
関数の中でしか使えません。
例:awaitの基本
async function fetchData() {
const response = await fetch("https://api.example.com/data");
const data = await response.json();
console.log(data);
}
fetchData();
fetch
関数: サーバーにリクエストを送り、データを取得するための関数です。await
の動作:fetch
がデータを返すまで待機し、その結果をresponse
に格納します。
Promiseとの違いを比較しよう
非同期処理の仕組みとしては、以前からPromiseがよく使われていました。しかし、コードが複雑になりやすいという課題がありました。
Promiseを使ったコード
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
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.error(error);
}
}
fetchData();
async / awaitでのエラーハンドリング
非同期処理が失敗した場合(例えば、サーバーに接続できないなど)、エラーを適切に処理する必要があります。async / await
では、try-catch
文を使います。
例:エラーハンドリング
async function fetchData() {
try {
const response = await fetch("https://api.example.com/data");
if (!response.ok) {
throw new Error("Network response was not ok");
}
const data = await response.json();
console.log(data);
} catch (error) {
console.error("Fetch error:", error);
}
}
fetchData();
try
ブロック: 正常な処理を実行する。catch
ブロック: エラーが発生した場合に処理を行う。
応用:複数の非同期処理を同時に扱う
複数の非同期処理を効率よく扱うには、Promise.allを使うのが一般的です。
例:複数の非同期処理を同時に実行
async function fetchMultipleData() {
const urls = [
"https://api.example.com/data1",
"https://api.example.com/data2"
];
try {
const promises = urls.map(url => fetch(url).then(res => res.json()));
const results = await Promise.all(promises);
console.log(results);
} catch (error) {
console.error("Error fetching data:", error);
}
}
fetchMultipleData();
解説:
map
: 各URLに対してfetch
を実行し、それぞれの結果をPromiseとして返します。Promise.all
: 配列内のすべてのPromiseが解決されるまで待機します。
async / awaitのメリット・デメリット
メリット
メリットは以下4つです。
コードの可読性が向上する
非同期処理を同期処理のように記述できるため、コードの流れが明確になります。
例えば、以下のPromise
とasync / await
の比較を見てください。
Promiseを使ったコード
fetch("https://api.example.com/data")
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error(error));
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.error(error);
}
}
fetchData();
ポイント: .then()
や.catch()
をネストする必要がなく、処理の流れが一目で理解しやすい。
エラーハンドリングが簡単
try-catch
文を使えば、エラー処理を一箇所にまとめることができます。
これにより、複数の.catch()
を使う必要がなくなり、コードの保守性が向上します。
デバッグがしやすい
非同期処理の中でも、await
を使ったコードは同期処理のようにデバッグできます。
例えば、ステップごとに処理を追いやすく、ブラウザの開発者ツールでブレークポイントを設置しやすい点がメリットです。
複雑な非同期ロジックの実装が容易
複数の非同期処理を順番に実行する場合や、条件に応じて処理を切り替える場合も、async / await
なら簡潔に記述できます。
デメリット
デメリットは以下4つです。
直列処理によるパフォーマンス低下の可能性
await
を使うと、各非同期処理が完了するまで次の処理に進まないため、非効率になる場合があります。
例えば、次のコードでは非同期処理が直列的に実行され、全体の処理時間が長くなります。
async function fetchData() {
const data1 = await fetch("https://api.example.com/data1");
const data2 = await fetch("https://api.example.com/data2");
console.log(data1, data2);
}
改善案:並列処理を使う
async function fetchData() {
const [data1, data2] = await Promise.all([
fetch("https://api.example.com/data1"),
fetch("https://api.example.com/data2")
]);
console.log(data1, data2);
}
async関数外では使えない
await
はasync
関数の中でしか使えません。そのため、グローバルスコープでの利用が制限されます。
// エラー:SyntaxError: await is only valid in async function
const result = await fetch("https://api.example.com/data");
初心者には仕組みが分かりづらい
内部でPromise
を扱っているため、async / await
の背後にある非同期処理の仕組みを理解していないと、意図しない挙動に戸惑うことがあります。
エラー処理を忘れるとバグの原因に
try-catchを使わずに非同期処理を書くと、エラーがキャッチされずに処理が失敗する可能性があります。
そのため、常にエラー処理を意識する必要があります。
まとめ
本記事では、Javascriptのasync/awaitについて解説しました。
async / await
は、非同期処理を簡潔かつ直感的に記述できる方法です。これにより、複雑なコードも読みやすく、保守しやすくなります。
何か不明点などございましたらコメント欄に記載頂けたらと思います!
以上、最後までお読みいただきありがとうございました。