JavaScriptのasync/await完全ガイド!初心者でもわかる非同期処理の基本と使い方
生徒
「先生、JavaScriptで時間のかかる処理を順番に実行したいんですけど、どうしたらいいですか?」
先生
「それなら、JavaScriptのasync/await構文を使うと簡単に書けます。非同期処理を直感的に順番通りに実行できますよ。」
生徒
「非同期処理って難しそうなんですが、具体的にどういう意味ですか?」
先生
「非同期処理とは、時間のかかる処理を待たずに他の処理を進められる仕組みです。でもasync/awaitを使うと、まるで順番に処理しているように書けます。」
生徒
「なるほど!じゃあ具体的な書き方を教えてください!」
先生
「では、基本から順番に見ていきましょう。」
1. async/awaitとは何か?
JavaScriptのasync/await構文は、非同期処理をわかりやすく書くための仕組みです。通常、非同期処理はPromiseを使って書きますが、複雑な処理になるとコードが読みにくくなります。async/awaitを使うと、まるで同期処理のように順番に処理を書けるので、初心者でも理解しやすくなります。
2. async関数の基本
async/awaitを使うには、まずasyncキーワードで関数を定義します。async関数は必ずPromiseを返す関数になります。
async function greet() {
return "こんにちは";
}
greet().then(message => {
console.log(message);
});
こんにちは
このように、asyncを付けるだけで、関数の戻り値が自動的にPromiseになります。
3. awaitで非同期処理を待つ
awaitはPromiseの完了を待つためのキーワードです。awaitはasync関数の中でしか使えません。これを使うと、処理の順番がわかりやすくなります。
function wait(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
async function run() {
console.log("処理開始");
await wait(2000); // 2秒待つ
console.log("2秒後の処理");
}
run();
処理開始
(2秒後)
2秒後の処理
上の例では、awaitで2秒待ってから次の処理が実行されるので、順番が自然に読めます。
4. 複数の非同期処理を順番に実行する
複数の非同期処理を順番に実行したい場合も、awaitを使うと簡単に書けます。
async function fetchData() {
console.log("データ1取得中...");
await wait(1000);
console.log("データ1取得完了");
console.log("データ2取得中...");
await wait(1000);
console.log("データ2取得完了");
}
fetchData();
データ1取得中...
(1秒後)
データ1取得完了
データ2取得中...
(1秒後)
データ2取得完了
awaitを使うことで、Promiseのthenチェーンを書かなくても自然に順番通りの処理が書けます。
5. エラーハンドリングの方法
async/awaitでは、try...catchを使ってエラーを簡単に扱うことができます。これにより、非同期処理でのエラーも同期処理のように扱えます。
async function fetchDataWithError() {
try {
await Promise.reject("データ取得エラー");
} catch (error) {
console.log("エラーをキャッチ:", error);
}
}
fetchDataWithError();
エラーをキャッチ: データ取得エラー
このように、awaitを使った非同期処理でも、簡単にエラー処理を書けます。
6. 複数のPromiseを並列で処理する
複数の非同期処理を同時に実行したい場合は、Promise.allと組み合わせると便利です。awaitを使うと、全ての処理が完了するまで待つことができます。
async function fetchAll() {
const promise1 = wait(1000).then(() => "データA");
const promise2 = wait(2000).then(() => "データB");
const results = await Promise.all([promise1, promise2]);
console.log("全てのデータ取得完了:", results);
}
fetchAll();
全てのデータ取得完了: ["データA", "データB"]
このように、複数の非同期処理を並列で実行する場合も、async/awaitを組み合わせることでコードがシンプルに書けます。
7. 実践!APIからデータを取得する例
実際のWebアプリケーションでは、APIからデータを取得することがよくあります。async/awaitを使うと、簡単に書けます。
async function getUser() {
try {
const response = await fetch("https://jsonplaceholder.typicode.com/users/1");
const data = await response.json();
console.log("ユーザー情報:", data);
} catch (error) {
console.log("データ取得エラー:", error);
}
}
getUser();
ユーザー情報: {id: 1, name: "Leanne Graham", ...}
fetch関数もPromiseを返すので、awaitを使うことで順番通りに処理できます。エラー処理もtry...catchで簡単に書けます。
8. async/awaitを使うときの注意点
async/awaitは便利ですが、いくつか注意点があります。まず、awaitはasync関数の中でしか使えません。また、非同期処理が長時間かかる場合はUIが固まる可能性があるため、必要に応じて並列処理や非同期イベントを組み合わせることが大切です。
さらに、Promiseを返す関数にasyncを付けると自動でPromise化されるので、二重にPromise化する必要はありません。無駄なネストを避けてシンプルに書くことを意識しましょう。
まとめ
今回の記事では、JavaScriptの非同期処理を扱う上で非常に重要なasync/awaitの基本から応用までを詳しく解説しました。
まず、async関数は非同期処理を行う関数として定義でき、必ずPromiseを返すことを確認しました。これにより、非同期処理の結果を後からthenやawaitで扱えるようになります。
次に、awaitを使うことで、Promiseの完了を待ってから次の処理を進められることを学びました。これにより、従来の複雑なthenチェーンを使わずに、まるで同期処理のようにコードを直感的に書けるようになります。
また、複数の非同期処理を順番に実行する場合は、単純にawaitを並べるだけで済むこと、さらに並列で実行したい場合はPromise.allと組み合わせることで効率的に処理できることを紹介しました。
エラーハンドリングについても、try...catchを使うことで、非同期処理でも簡単に例外をキャッチできる点を学びました。特にAPIからのデータ取得など、実際のWeb開発でよく発生するケースでも、エラー処理をわかりやすく書くことが可能です。
さらに、async/awaitを使う際の注意点として、awaitは必ずasync関数内で使用すること、非同期処理がUIに影響を与える可能性がある場合は適切に並列処理を活用すること、そして不要な二重Promise化を避けることが重要であることも理解しました。
実際のサンプルコードを通して、非同期処理の順序制御、並列処理、エラーハンドリングの方法を実践的に確認できました。
これらの知識は、Webアプリケーション開発において非常に役立ち、API通信、データベースアクセス、タイマー処理など、さまざまな場面で応用できます。async/awaitを正しく理解することで、コードの可読性と保守性が大幅に向上し、エラー処理もシンプルに書けるようになります。
実践例のポイントまとめ
- async関数は必ずPromiseを返すことを確認する
- awaitは非同期処理の完了を待つためのキーワードで、async関数内で使用する
- 複数の非同期処理は順番にawaitを並べるだけで順序制御可能
- 複数処理を並列実行する場合はPromise.allを活用する
- try...catchで非同期処理のエラーを同期処理のように扱える
- 不要な二重Promise化を避け、シンプルなコードを意識する
- UIの負荷を考え、必要に応じて並列処理や非同期イベントと組み合わせる
生徒
「先生、今回のasync/awaitの使い方は理解できました。順番に処理を書く場合はawaitを使えば良くて、並列に実行したい場合はPromise.allと組み合わせるんですね。」
先生
「そうです。順番通りの処理と並列処理の両方を使い分けられるようになると、Webアプリの非同期処理がとても書きやすくなります。」
生徒
「エラーハンドリングもtry...catchで簡単にできるので、以前よりコードが読みやすくなりました。」
先生
「その通りです。非同期処理でも同期処理のようにエラーを扱えるのがasync/awaitの大きな利点です。実務ではAPI通信やデータベース操作などで特に役立ちます。」
生徒
「なるほど、async/awaitを正しく理解すると、コードの保守性も高まるんですね。今日学んだ内容を実際にプロジェクトで使ってみたいです。」
先生
「そうですね。まずは小さな非同期処理から試して、徐々に複雑な処理に挑戦していくと良いでしょう。今回の例を参考にすれば、APIからのデータ取得やタイマー処理もスムーズに実装できます。」
生徒
「わかりました!今日学んだことを復習しながら、async/awaitを使ったプログラムを書いてみます。」
先生
「良いですね。繰り返し実践することで、非同期処理の理解が深まり、実務でも即戦力として活用できるようになります。」
サンプルコード復習
async function fetchExample() { try { const response1 = await fetch("https://jsonplaceholder.typicode.com/posts/1"); const data1 = await response1.json(); console.log("Post1:", data1);
const response2 = await fetch("https://jsonplaceholder.typicode.com/posts/2");
const data2 = await response2.json();
console.log("Post2:", data2);
} catch (error) {
console.log("エラー発生:", error);
}
}
fetchExample();
Post1: {userId: 1, id: 1, title: "タイトル1", body: "本文1"}
Post2: {userId: 1, id: 2, title: "タイトル2", body: "本文2"}
このようにasync/awaitを使うことで、非同期処理を順序通りに実行しつつ、エラーハンドリングも簡単に行えます。順序制御、並列処理、例外処理の基本をしっかり押さえて、実践で活用できるようにしましょう。