はじめに
非同期処理を扱う方法はJavaScriptにいくつかありますが、今ではasync/awaitが主流となっています。 async/awaitは、Promiseよりもシンプルで、コードの見通しが良くなる という利点があります。ただ、使い方に慣れていないと難しく感じることもあるでしょう。「Promiseとどう違うの?」「どっちを使えばいいの?」と疑問に思う方もいるかもしれません。
この記事では、そういった疑問を解消するために、async/awaitの仕組みやそのメリット、Promiseとの違いを詳しく解説します。**async/awaitをしっかり理解することで、非同期処理の扱い方がスムーズになり、コード記述がしやすくなります。**非同期処理を扱うことは現在のWeb開発に必須のスキルとなりますので、一緒に学んでいきましょう!
この記事について
目的
- async/awaitを理解する
- Promiseとの違いを知る
- async/awaitを使用してデータ操作ができるようになる
対象者
- 初学者の方
- JavaScriptの勉強を最近始めた方
JavaScriptの基本について
この記事ではJavaScriptの基本的な説明には触れていません。JavaScriptの基礎や実践ハンズオンを以下の記事で紹介していますので、理解を深めたい方はぜひご覧ください。
https://envader.plus/article/331
async/awaitについて
JavaScriptにおけるasync/awaitとは、非同期処理でデータを取得する際に使用される関数です。asyncは関数の前に付けることで、その関数が非同期処理を行うことを宣言します。この関数は必ずPromiseを返します。
非同期処理とは、ある処理が終わるのを待たずに次の処理に進む動作のことを指します。サーバーからデータを取得するなど、時間のかかる処理を待っている間も、他のプログラムが進行できる仕組みです。
async関数の中では、awaitという構文を使って、非同期処理が終わるまで一時停止することができます。awaitは、Promiseが解決(成功)または拒否(失敗)されるまで待ちます。通常、非同期処理では、その処理が完了する前に次の行のコードが実行されますが、awaitを使うと、その処理が終わるまで次の処理を待つようになります。asyncとawaitは、通常セットで使用します。awaitはasync関数の中でしか使えないため、非同期処理を扱うときは、この二つを一緒に使うのが一般的です。
このように、async/awaitを使うことで、非同期処理を順序通りに書けるため、コードの可読性が向上し処理の流れが理解しやすくなります。
async/awaitが導入された背景
async/awaitは、非同期処理で使用するコールバック関数やPromiseよりも、コードの可読性と管理をしやすくするために導入された構文です。async/awaitはPromiseをベースにしており、基本的には同じ目的で使用しますが、コードの可読性と記述のしやすさに重点を置いて設計されています。
非同期処理を実現するために、最初はコールバック関数が使われていました。コールバック関数では、非同期処理が終わった後に実行される関数を渡します。しかし、処理が複雑化するとコードのネストが深くなる「コールバック地獄」と呼ばれる現象が発生し、コードの可読性が低下し管理が難しくなります。この問題を解決するためにPromiseが導入されました。しかし、非同期処理が連続したり、複数のPromiseを組み合わせるなど、処理が複雑化するとPromiseでの管理も難しくなることがあります。
そこで、コールバック関数やPromiseの課題を解決するためにasync/awaitが登場しました。async/awaitはコードのネストを避け、シンプルに記述できるのが特徴です。その直感的で分かりやすい手法により、Pythonなど他の言語でも採用されています。
async/awaitとPromiseの使い分け
非同期処理にはいくつかの書き方がありますが、実際の開発ではどれを使えば良いのか悩む方もいるかもしれません。私自身も、複雑でない処理ならPromiseでも十分では?と疑問に思ったことがあります。
現在、非同期処理の記述ではasync/awaitが主流です。async/awaitはPromiseの発展型として導入されており、非同期処理の流れや管理がしやすく、多くの開発現場で採用されています。これら2つをどう使い分けるかは、コードの複雑さや実行したい処理に応じて選択すると良いでしょう。
たとえば、コードの可読性を上げたい場合や、非同期処理を順番に実行したい場合はasync/awaitが適しています。一方で、シンプルな処理や複数の非同期処理を並行して実行したい場合には、Promiseが有効です。このように、処理内容に応じて使い分けるのが良いかと思います。
なお、Promiseも非同期処理の基本を支える概念であり、async/awaitもその背後ではPromiseを利用しているため、どちらも仕組みを理解しておく必要があります。
Promiseについては以下の記事で詳しく解説していますので、ぜひご覧ください。
https://envader.plus/article/468
async/awaitの使い方
async/awaitの基本について学びました。async/awaitは「コードの可読性と管理をしやすくするために導入された構文」と学びましたが、実際にどのように記述するか、Promiseでの処理との違いをコード例とあわせて確認しましょう。
以下のコードは、async/awaitの基本的な使い方を示しています。これを使うことで、JavaScriptの非同期処理を簡単に書くことができます。
// 関数名にasyncをつけてasyncで非同期処理をする
async function asyncFunc() {
return 'async-値';
}
// asyncFunc関数はPromiseを返す
asyncFunc().then((value) => {
console.log(value); // => 'async-値'
});
コードの解説
// 関数名にasyncをつけてasyncで非同期処理をする
async function asyncFunc() {
return 'async-値';
}
async を使って関数を定義しています。この async キーワードを関数の前につけると、その関数は必ず Promise を返すようになります。関数内で何か値を返した場合、その値は自動的に Promise.resolve()
で包まれ、Promise オブジェクトとして扱われます。
// asyncFunc関数はPromiseを返す
asyncFunc().then((value) => {
console.log(value); // => 'async-値'
});
asyncFunc().then()
メソッドを使うことで、非同期処理が完了したときの値を受け取ることができます。この場合、then((value) => {...})
の部分では、Promise が完了すると、その結果である 'async-値'
が value
に渡されます。その後、この value
は次の処理である console.log()
に渡され、出力結果として 'async-値'
が表示されます。
このコードを通じて理解しておきたいポイント
async を使うと、関数の処理結果が自動的に Promise になるため、明示的に作成する必要がなくなります。通常の Promise では以下のように、Promise.resolve()
や Promise.reject()
を使ってPromiseを作成し、その結果を処理しますが、asyncを使えばこれを省略できます。
たとえば、Promiseを使った場合は次のように書かなければいけません。
function promiseFunc() {
return Promise.resolve('値');
}
promiseFunc().then((value) => {
console.log(value);
});
一方、asyncを使うと次のようにシンプルになります。
async function asyncFunc() {
return '値';
}
asyncFunc().then((value) => {
console.log(value);
});
このように、asyncを使うことで Promise.resolve()
を自分で書かなくても、関数内で単に return
すればその値が自動的に Promiseでラップされます。この例のコードはシンプルなため、asyncの効果をさほど感じないかもしれませが、コードが複雑になるにつれ、非同期処理を扱う際の手間が減り、コードが読みやすくなることを実感できるかと思います。
async/awaitを使ってみよう
これまでに、async/awaitの基本的な使い方やコードの書き方を学びました。このセクションでは、実際にasync/awaitを使ってコードを書き、ハンズオン形式で理解を深めていきましょう。今回は、POSTメソッドを使用してサーバーにデータを送信します。
今回のハンズオンでは、JSONPlaceholderというAPIサービスを利用します。JSONPlaceholderは、開発者がAPIを使ってデータのやり取りを練習できる、無料のオンラインモックAPIサービスです。
-
JSONPlaceholder
また、ブラウザ上で直接コードを試したい方には、以下のサイトをおすすめします。フロントエンドの環境構築が不要で、すぐにasync/awaitのコードを実行できます。
-
StackBlitz
-
StackBlitzについての詳しい解説は、以下のサイトでご覧いただけます。
async/awaitを使用したデータのPOSTメソッドの送信
今回のハンズオンでは以下のファイルを編集し、POSTメソッドを使用してJSONPlaceholderへデータを送信します。
- index.html
- main.js
index.htmlの内容は以下の通りです。ここで、main.jsファイルを読み込みます。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>asyncAwait</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/main.js"></script>
</body>
</html>
次に、main.jsでasync/awaitを使ってデータを送信するコードを書きます。非同期処理を行い、サーバーへPOSTメソッドを使用してデータを送信する関数を定義します。
// main.js
// async関数を使ってデータをPOSTメソッドで送信
async function postData() {
const url = 'https://jsonplaceholder.typicode.com/posts'; // JSONPlaceholderのPOSTエンドポイント
const data = {
title: 'エンベーダー',
body: 'エンジニア予備軍のためのITインフラ学習ゲーム',
userId: 1,
};
try {
const response = await fetch(url, {
method: 'POST', // HTTPメソッドをPOSTに指定
headers: {
'Content-Type': 'application/json', // 送信データの形式を指定
},
body: JSON.stringify(data), // JavaScriptオブジェクトをJSON形式に変換して送信
});
const result = await response.json(); // サーバーからの応答をJSONとして取得
console.log('送信内容:', result); // 結果を表示
} catch (error) {
console.error('エラーが発生しました:', error); // エラーハンドリング
}
}
// 関数を実行
postData();
コードを編集後、index.htmlをブラウザで開き、開発者ツールのConsoleを確認します。以下のように送信内容がConsoleに表示がされていれば、POST送信が成功したことになります。
コードの解説
今回のハンズオンではasync/awaitのPOSTメソッドを使用して、JSONPlaceholderへデータを送信しました。コードを1つずつ確認していきましょう。
-
async関数の作成と送信先、値の定義
// async関数を使ってデータをPOSTメソッドで送信 async function postData() { const url = 'https://jsonplaceholder.typicode.com/posts'; // JSONPlaceholderのPOSTエンドポイント const data = { title: 'エンベーダー', body: 'エンジニア予備軍のためのITインフラ学習ゲーム', userId: 1, };
async関数を作成し、データの送信先と値を定義しています。値のキーはJSONPlaceholderで説明されているものを使用しています。
キーや値、メソッドの解説は以下のページで確認していただけます。
-
メソッドを指定してAPIへデータ送信
try { const response = await fetch(url, { method: 'POST', // HTTPメソッドをPOSTに指定 headers: { 'Content-Type': 'application/json', // 送信データの形式を指定 }, body: JSON.stringify(data), // JavaScriptオブジェクトをJSON形式に変換して送信 }); const result = await response.json(); // サーバーからの応答をJSONとして取得 console.log('送信内容:', result); // 結果を表示 } catch (error) { console.error('エラーが発生しました:', error); // エラーハンドリング } }
-
メソッドと送信データ形式の指定
POST
メソッドを指定し、fetch関数を使用しサーバーへデータを送信します。headers:
内で送信するデータはJSON形式ということを{ 'Content-Type': 'application/json' }
で指定しています。サーバーは通常、JSON形式でデータを受け取るため、body: JSON.stringify(data)
で値をJSON形式に変換します。 -
awaitの定義
const result = await response.json();
部分では、awaitを使ってfetch
処理の完了を待ちます。処理完了後は、結果をresponse
変数に代入し、次の処理へ渡します。 -
try構文
エラーが発生する可能性がある処理を実行し、そのエラーを安全に処理するために使われます。もし
try
ブロック内の処理でエラーが発生した場合、そのエラーをcatch
して対応することができます。
-
このハンズオンでは、async/awaitを使って非同期処理を整理し、APIへデータを送信する流れを学ぶことができます。コードの可読性と管理をしやすくするために導入された構文ということを感じていただけるかと思います。async/awaitを使うことで、非同期処理を簡単に記述し管理できることがわかりました。
この記事で学んだこと
JavaScriptにおけるasync/awaitは、非同期処理を簡潔かつ直感的に記述するための構文です。従来使用されていたコールバック関数やPromiseに比べて、async/awaitはコードの可読性が高く、記述がシンプルになるよう設計されています。
現在、多くの開発現場で非同期処理の記述方法としてasync/awaitが主流となっています。async/awaitは、Promiseを基盤にしつつ、非同期処理の流れや管理を容易にするため、複雑な処理でも効率的に扱えます。どちらを使うかは、コードの複雑さや実行したい処理に応じて適切に選択すると良いでしょう。
参考資料
-
JavaScript Primer - 非同期処理:Promise/Async Function
-
MDN web docs - async function
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/async_function
-
wikipedia - Async/await , Promise
-
JavaScript Promiseの本
【番外編】USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
プログラミング塾に半年通えば、一人前になれると思っているあなた。それ、勘違いですよ。「なぜ間違いなの?」「正しい勉強法とは何なの?」ITを学び始める全ての人に知って欲しい。そう思って書きました。是非読んでみてください。
「フリーランスエンジニア」
近年やっと世間に浸透した言葉だ。ひと昔まえ、終身雇用は当たり前で、大企業に就職することは一種のステータスだった。しかし、そんな時代も終わり「優秀な人材は転職する」ことが当たり前の時代となる。フリーランスエンジニアに高価値が付く現在、ネットを見ると「未経験でも年収400万以上」などと書いてある。これに釣られて、多くの人がフリーランスになろうとITの世界に入ってきている。私もその中の1人だ。数年前、USBも知らない状態からITの世界に没入し、そこから約2年間、毎日勉学を行なった。他人の何十倍も努力した。そして、企業研修やIT塾で数多くの受講生の指導経験も得た。そこで私は、伸びるエンジニアとそうでないエンジニアをたくさん見てきた。そして、稼げるエンジニア、稼げないエンジニアを見てきた。
「成功する人とそうでない人の違いは何か?」
私が出した答えは、「量産型エンジニアか否か」である。今のエンジニア市場には、量産型エンジニアが溢れている!!ここでの量産型エンジニアの定義は以下の通りである。
比較的簡単に学習可能なWebフレームワーク(WordPress, Rails)やPython等の知識はあるが、ITの基本概念を理解していないため、単調な作業しかこなすことができないエンジニアのこと。
多くの人がフリーランスエンジニアを目指す時代に中途半端な知識や技術力でこの世界に飛び込むと返って過酷な労働条件で働くことになる。そこで、エンジニアを目指すあなたがどう学習していくべきかを私の経験を交えて書こうと思った。続きはこちらから、、、、
エンベーダー編集部
エンベーダーは、ITスクールRareTECHのインフラ学習教材として誕生しました。 「遊びながらインフラエンジニアへ」をコンセプトに、インフラへの学習ハードルを下げるツールとして運営されています。
関連記事
2020.02.25
完全未経験からエンジニアを目指す爆速勉強法
USBも知らなかった私が独学でプログラミングを勉強してGAFAに入社するまでの話
- キャリア・学習法
- エンジニア
2024.09.19
JavaScriptの基本、Fetch APIを理解しよう
この記事では、初めてFetch APIを使う方でも、使いこなせるようにわかりやすく解説していきます。この記事を通して、APIからデータを取得し、画面に表示する方法を学びます。基本を学び、JavaScriptの理解を深めていきましょう!
- JavaScript
- フロントエンド
2024.09.29
JavaScriptのライブラリ、Axiosを理解しよう
この記事では、Axiosの基本的な使い方と便利な機能について解説します。サーバーとのデータのやり取りは、Web開発において必須のスキルですので、ぜひ一緒に学んでいきましょう!
- JavaScript
- フロントエンド
2024.09.28
CORSを回避!CloudFront、S3、API Gatewayを使ってフロントエンドとAPIを同じドメインでデプロイ
このアプローチを使えば、CORSの設定を不要にし、セキュリティやパフォーマンスの向上、運用の簡素化など、実務上でも多くの利点が得られます。
- フロントエンド
- AWS