JavaScriptにおけるasync/await
この記事ではJavaScriptにおけるasync/awaitについて説明します。
YouTube Video
JavaScriptにおけるasync/await
JavaScriptのasync
(およびawait
)は、非同期処理をより直感的で読みやすい形で書くための機能です。これを使うことで、従来のコールバック関数やPromise
チェーンの複雑さを軽減し、非同期処理を同期的なコードのように書けるようになります。
async
関数
async
は、関数を非同期関数として定義するために使います。async
関数は、常にPromiseを返します。async
が付けられた関数内では、await
を使ってPromiseの結果が返ってくるまで待機することができます。
async
関数の基本構文
1async function myAsyncFunction() {
2 // Write asynchronous processing here
3 return 'Result'; // Return a Promise
4}
この場合、myAsyncFunction()
を呼び出すと、自動的にPromiseオブジェクトが返されます。Promiseが解決されると、その結果がreturn
で返された値になります。
例: 基本的なasync
関数
1async function greet() {
2 return 'Hello, World!';
3}
4
5greet().then((message) => {
6 console.log(message); // Displays "Hello, World!"
7});
await
await
は、Promiseが解決されるのを待つために使います。await
を使うことで、Promiseが解決するまで処理を一時停止し、Promiseの結果を受け取ることができます。await
は必ずasync
関数の中でのみ使用可能です。
例: await
の使い方
1async function fetchData() {
2 // Wait for the result of the Promise
3 const data = await fetch('https://codesparklab.com/json/example.json');
4 // Wait for the asynchronous operation to complete
5 const jsonData = await data.json();
6 // Retrieve and display the data
7 console.log(jsonData);
8}
9
10fetchData();
上記の例では、fetch
関数が返すPromiseをawait
で待ち、その結果を使ってさらに非同期処理を行っています。
async
/await
を使ったエラーハンドリング
async
関数の中でエラーが発生すると、そのエラーはPromiseのreject
として扱われます。try...catch
文を使って、エラーハンドリングを行うことができます。
例: エラーハンドリング
1async function fetchData() {
2 try {
3 // Invalid URL
4 const data = await fetch('https://invalid.codesparklab.com/');
5 const jsonData = await data.json();
6 console.log(jsonData);
7 } catch (error) {
8 // Catch the error
9 console.error('Failed to fetch data:', error);
10 }
11}
12
13fetchData();
try...catch
ブロックを使うことで、非同期処理中に発生するエラーを捕まえ、エラーが発生してもプログラムがクラッシュしないようにできます。
async
/await
のメリット
従来のPromise
チェーンと比較して、async
/await
は次のような利点があります。
- 高い可読性
- 非同期処理が同期処理のように記述できるため、ネストが深くなる
Promise
チェーンやコールバックの煩雑さを避けられます。
- 非同期処理が同期処理のように記述できるため、ネストが深くなる
- 簡単なデバッグ
- 同期的なコードに近いため、デバッグやエラーハンドリングが簡単になります。
- 高い保守性
- 非同期処理がシンプルに記述できるため、コードの変更や修正がしやすくなり、将来的なメンテナンス性が向上します。
例: Promise
チェーン vs async
/await
Promise
チェーンを使ったコードとasync
/await
を使ったコードを比較してみましょう。
1// Code using Promise chains
2function fetchDataPromise() {
3 fetch('https://codesparklab.com/json/example.json')
4 .then((response) => response.json())
5 .then((data) => {
6 console.log(data);
7 })
8 .catch((error) => {
9 console.error('Failed to fetch data:', error);
10 });
11}
12
13// Code using async/await
14async function fetchDataAsync() {
15 try {
16 const response = await fetch('https://codesparklab.com/json/example.json');
17 const data = await response.json();
18 console.log(data);
19 } catch (error) {
20 console.error('Failed to fetch data:', error);
21 }
22}
このように、async
/await
を使うと非同期処理が直線的に記述でき、より分かりやすいコードになります。
複数の非同期処理を同時に実行する
Promise.all()
やPromise.race()
などとawait
を組み合わせることで、複数の非同期処理を同時に実行し、その結果をまとめて扱うこともできます。
Promise.all()
1async function fetchMultipleData() {
2 try {
3 const [data1, data2] = await Promise.all([
4 fetch('https://codesparklab.com/json/example1.json'),
5 fetch('https://codesparklab.com/json/example2.json')
6 ]);
7 const jsonData1 = await data1.json();
8 const jsonData2 = await data2.json();
9 console.log(jsonData1);
10 console.log(jsonData2);
11 } catch (error) {
12 console.error('Failed to fetch data:', error);
13 }
14}
15
16fetchMultipleData();
Promise.all()
は、複数のPromiseを同時に解決し、その結果を配列として返します。すべてのPromiseが解決されるまで待機し、どれか1つでも失敗すると全体が失敗とみなされます。
Promise.race()
1async function fetchFastestData() {
2 try {
3 const fastestResponse = await Promise.race([
4 fetch('https://codesparklab.com/json/example1.json'),
5 fetch('https://codesparklab.com/json/example2.json')
6 ]);
7 const jsonData = await fastestResponse.json();
8 console.log('Fastest data:', jsonData);
9 } catch (error) {
10 console.error('Fetch error:', error);
11 }
12}
13
14fetchFastestData();
Promise.race()
は、最初に解決または拒否されたPromiseの結果を返します。複数の非同期処理のうち、最も早く完了したものに反応したい場合に便利です。ただし、最初に失敗したPromiseがあると即座にcatchに入ります。
Promise.allSettled()
1async function fetchWithAllSettled() {
2 const results = await Promise.allSettled([
3 // This URL will success
4 fetch('https://codesparklab.com/json/example1.json'),
5 // This URL will fail
6 fetch('https://invalid.codesparklab.com/')
7 ]);
8
9 results.forEach((result, index) => {
10 if (result.status === 'fulfilled') {
11 const url = result.value.url;
12 console.log(`Request ${index + 1} succeeded:`, url);
13 } else {
14 const reason = result.reason;
15 console.warn(`Request ${index + 1} failed:`, reason);
16 }
17 });
18}
19
20fetchWithAllSettled();
Promise.allSettled()
は、成功・失敗に関わらず全ての結果を待ちます。それぞれの結果が{ status, value }
または{ status, reason }
の形式で返されるため、どれが成功し、どれが失敗したのかを確認できます。
Promise.any()
1async function fetchAnySuccessful() {
2 try {
3 const firstSuccessful = await Promise.any([
4 // This URL will fail
5 fetch('https://invalid.codesparklab.com/'),
6 // This URL will success
7 fetch('https://codesparklab.com/json/example1.json')
8 ]);
9 const jsonData = await firstSuccessful.json();
10 console.log('First successful response:', jsonData);
11 } catch (error) {
12 console.error('All fetch requests failed:', error);
13 }
14}
15
16fetchAnySuccessful();
Promise.any()
は、最初に成功したPromiseの結果だけを返します。すべてが失敗した場合のみ例外が投げられます。一部のAPIが不安定な環境で、成功するまでリトライ的に使うこともできます。
まとめ
async
関数: 常にPromiseを返し、非同期処理を記述するために使います。await
: Promiseが解決されるまで待機し、結果を受け取るために使います。- エラーハンドリング:
try...catch
を使って、非同期処理中に発生するエラーを処理します。 - 複数の非同期処理:
Promise.all()
などを使うことで、複数の非同期処理を同時に実行できます。
async
/await
は、非同期処理を扱う上で強力なツールなので、複雑な非同期ロジックをシンプルにするためにぜひ活用してください。
YouTubeチャンネルでは、Visual Studio Codeを用いて上記の記事を見ながら確認できます。 ぜひYouTubeチャンネルもご覧ください。