初心者にも分かりやすいasync/awaitの機能の説明(JavaScript)

JavaScriptでプログラムを書いていると、async/awaitという、なんだか分かったような分からないような文法に出会うことがありますよね。

「asyncは非同期?な関数につける構文?」
「asyncって関数につけると、関数の中でawaitって使えるようになる?」
「awaitって書いた後に、async関数を実行すると、普通に動くようになる?」

なんだか少し難しい文法のように感じます。

この記事では、プログラミング初心者がJavaScriptを学ぶにあたって、少し難しいと感じる事の多い、async/awaitの機能の要点を分かりやすく説明いたします。

以下の流れで説明します。

  1. 非同期処理って何?
  2. asyncを関数につけると?
  3. awaitをつけて関数を実行すると?
  4. まとめ

 

1. 非同期処理って何?

async/awaitとは、JavaScriptで非同期処理を行う時に用いる構文です。
では、そもそも非同期処理とは何でしょうか?

非同期処理とは「待っている間に、他のことをできるようにする仕組み」の事です。

「待っている間に、他のことをできるようにする仕組み」とはどういう事か、
銀行に例えてみましょう。

銀行にAさんがお金を引き出しに来ました。
Aさんが、銀行の窓口で「1万円お金を引き出したい」と伝えると「お待ちください」と伝えられました。

そして、銀行の窓口では、次の人のお話を聞きます。
Aさんのお金の引き出しが終わるまで、窓口の人が何もできなくなるわけではありません。
Aさんのお金の引き出しが終わるまでの間も、窓口の人は次のお客様の対応ができます。
すなわち、銀行の窓口は「待っている間に、他のことをできる」のです。

 

これは当たり前のことのように思えます。
しかし、実はプログラムで考えてみると、ちょっと難しいことなのです。

お金の引き出しを行う関数 hikidashi があったとします。
この関数 hikidashi を呼び出してしまうと、その実行が終わるまで、
次の行に進めません。

function hikidashi(){
  return 10000;
}

console.log('お金を引き出します');
const result = hikidashi();
console.log(result);
console.log('次のお客様に対応します');

こちらのプログラムの実行結果は次の通りです。

お金を引き出します
10000
次のお客様に対応します

先に10,000円引き出す処理が実行されてしまいました。

このように、通常、プログラムは上から順番に処理を実行します。1つの処理が終わるまで次の処理は実行されません。
このように処理が行われる仕組みを、同期処理と呼びます。

一方で、プログラムでも今回の引き出し処理の例のように「待っている間に、他のことをできる」ようであって欲しい事は多々あります。

例えば、SNSで全ての投稿の画像がダウンロードされて表示されるまで、アプリが止まってしまったら凄く不便です。
また、ゲームのアプリで、CPUのキャラクターが動いている間、自分のキャラクターが動けないようであれば、多くのゲームは成立しません。

このような問題を解決し、「待っている間に、他のことをできるようにする仕組み」が非同期処理です。

2. asyncを関数につけると?

それでは、JavaScriptで非同期処理を実現するには、どのようにすればよいでしょうか?
その1つの方法にasync/awaitがあります。
(エーシンク/アウェイトと読みます)

ここでは、asyncの機能について説明していきます。
asyncは関数の宣言の前につけます。
asyncがつけられた関数は非同期に処理されるようになります。

先ほどのhikidashi関数にasyncをつけてみましょう。

async function hikidashi(){
  return 10000;
}

console.log('お金を引き出します');
const result = hikidashi();
console.log(result);
console.log('次のお客様に対応します');

このプログラムの実行結果は次の通りです。

お金を引き出します
Promise {<fulfilled>: 10000} ※
次のお客様に対応します

※2行目の表示内容は実行環境によって異なります。

先ほどとは異なり、Promiseから始まる文字列が表示されました。これはPromiseクラスのオブジェクトです。
それでは、このPromiseオブジェクトから、実際に10,000という値を取り出すにはどうすればよいでしょうか?

以下のように書き換える事で、取り出す事ができます。

async function hikidashi(){
  return 10000;
}

console.log('お金を引き出します');
hikidashi().then((result)=>console.log(result));
console.log('次のお客様に対応します');
Promiseオブジェクトから関数の戻り値を取り出す時は、then関数を呼び出します。then関数の引数に、元の関数(この場合はhikidashi関数)の戻り値が代入されています。

このプログラムの実行結果は次の通りです。

お金を引き出します
次のお客様に対応します
10000

このように、プログラムを記述した順番とは違う順番で出力されました。
hikidashi()の後のthen((result)=>console.log(result))hikidashi()の処理が終わったら、console.log(result)を実行することを意味します。

これによって、先に「次のお客様への対応」を実行して、その後に10,000円を表示するプログラムを実現できました。
asyncを付けた関数によって非同期処理を実現できたのです。

3. awaitをつけて関数を実行すると?

それでは、awaitはどのような機能なのでしょうか?

さきほど、asyncを付けた関数の実行結果は、Promiseというオブジェクトが返されることが分かりました。
そして、その処理結果を取得するために、thenというメソッドを呼び出しました。

このように、asyncを使うと非同期処理を簡単に実装できます。
しかし、一方で、asyncがついている関数を今回だけは同期的に呼び出したい場合、つまり、呼び出し結果が得られるまで次の処理を実行したくない場合は、どうしたら良いのでしょうか。
このような時には、awaitを使うと次のように書けます。
async function hikidashi(){
  return 10000;
}

console.log('お金を引き出します');
let result = await hikidashi();
console.log(result);
console.log('次のお客様に対応します');

hikidashi関数の呼び出しの前にawaitを書き加えただけの、非常にシンプルな記述です。
このプログラムの実行結果は、次の通りです。

お金を引き出します
10000
次のお客様に対応します

awaitをつけたことによって、resultにはPromiseオブジェクトではなく、直接10,000が格納されるようになりました。
このように、awaitによって、シンプルな記述で、非同期関数を同期的に実行できます。

4. まとめ

本記事では以下の内容について紹介してきました。

  • 非同期処理とは「待っている間に、他のことをできるようにする仕組み」
  • JavaScriptでは、asyncを用いて非同期処理を実現可能
  • awaitは、asyncをつけた関数を同期的に実行できるようにするもの

説明は以上です。

カサレアルでは、JavaScriptを学ぶ方に向けて「JavaScriptで学ぶ初めてのプログラミング」や「モダンJavaScript入門」「JavaScript応用」などのコースを開催しています。

JavaScriptに関するコースの詳細や開催日程に関しては以下のリンクをご覧ください。

フロントエンド開発を学ぶ研修一覧
https://www.casareal.co.jp/ls/service/openseminar/search/frontend

--------------------------
開発支援・技術研修のご要望・ご相談はこちらから
--------------------------
【この技術ブログを読んだエンジニアの皆様へ】
カサレアルブログをお読みいただき、ありがとうございます!

私たちは、常に新しい技術に挑戦し、ユーザーのニーズに応えるサービスを提供しています。
もし、当社の技術への情熱や、会社・チーム・社員の雰囲気に共感いただけたなら、
ぜひ私たちと一緒に働きませんか?
現在、株式会社カサレアルでは事業拡大に伴い、新たな仲間となるエンジニアを積極的に募集しています。

少しでも興味をお持ちいただけましたら、まずは弊社のことを知っていただけると嬉しいです。
▼採用サイト
https://www.casareal.co.jp/recruit/career
▼社員インタビュー
https://hrmos.co/pages/casareal/jobs/0000016
▼エンジニアの仲間になる! エントリーはこちらから
https://hrmos.co/pages/casareal/jobs

皆様のエントリーを心よりお待ちしています!

ポリモーフィズムでつまずいてた過去

コメントを残す

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

コメント ※

名前 ※

メール ※

サイト