【JavaScript】async/awaitで非同期処理の処理順をコントロールする方法




下の記事でPromiseを利用した非同期処理のコントロールについて解説しました。このページでは更に進んでasync/awaitを利用して非同期処理の処理順をコントロールする方法について解説していきます。

【JavaScript】「Promise」で非同期処理の処理順をコントロールする方法

2019年9月14日

実は、async/awaitを利用することで更にコードをシンプルに記述することが出来ます。Promiseとはなにかということが分からないと理解が難しいと思うので、不安な方は上の記事から先に読むことをオススメいたします。

目次

async/awaitとは

具体的なソースコードは後で見ていくとして、async/awaitの概要について見ていきます。

async

まずは公式ドキュメントから引用します。

async function 宣言は、 AsyncFunction オブジェクトを返す 非同期関数 を定義します。非同期関数は非同期でイベントループを介して実行され、暗黙的にPromiseを返します。なおコードのシンタックス及び構造は通常の同期関数と非常に似たものになります。

async function – JavaScript | MDN

ポイントは以下です。

  • 非同期関数を定義することが出来る
  • 暗黙的にPromiseを返す

await

まずは公式ドキュメントから引用します。

await 式は、async 関数の実行を一時停止し、 Promise の解決を待ちます。そして async 関数の実行を再開し、解決された値を返します。キーワード await は、async 宣言された関数の中でのみ有効です. async 関数の外で使用した場合は SyntaxErrorとなります。

async function – JavaScript | MDN

ポイントは以下です。

  • awaitの箇所に来たときにasync関数の実行を一時停止する
  • Promiseが返ってきたら処理を再開する
  • awaitはasync関数内でしか使えない

実際のコードを見てみる

function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  var result = await resolveAfter2Seconds();
  console.log(result);
}

asyncCall();

//結果
//calling
//resolved

十分にシンプルだったので、公式ドキュメントの例をそのまま持ってきました。

ポイントは9行目〜13行目です。ここでasync関数を定義していますね。asyncCall()を実行すると以下のような処理が行われます。

  1. console.log(‘calling’)が実行される
  2. awaitに遭遇したのでasyncCall()の処理を中断する
  3. resolveAfter2Seconds()を実行する
  4. 2000ミリ秒後にresolveAfter2Seconds()からresolve(‘resolved’)が返ってくる
  5. asyncCall()はresolveを受け取ったので処理を再開する
  6. console.log(result)を実行する

async/awaitを使うメリット

ではPromiseだけを使った場合に比べてどのようなメリットがあるのでしょうか?それは「thenが多くつながる場合は特にコードがシンプルになる」という点があります。

Promiseだけの場合

function sayHello(){
  return new Promise(function(resolve, reject){
    setTimeout(function(){
      console.log('Hello');
      resolve();
    }, 1000);
  });
}
 
sayHello()
    .then(function() {
      console.log('world!');
    })
    .then(function() {
      console.log('My name is Keita!');
    });

async/awaitを使った場合

function sayHello(){
  return new Promise(function(resolve, reject){
    setTimeout(function(){
      console.log('Hello');
      resolve();
    }, 1000);
  });
}

async function doFunc(){
  var result = await sayHello();
  console.log(result);
  console.log('world!');
  console.log('My name is Keita!');
}

doFunc();

異なるのは10行目以降です。thenをつないでいくとコールバック関数を何度も呼び出すことになり複雑になっていきます。特にthenを何度も繰り返し使うような場合はasync/awaitを使うメリットが大きくなっていきます。

コールバック関数を何度も使うことが無いので、見た目がシンプルになり処理の順番がわかりやすいのです。このように、async/awaitをうまく活用することでコードの可読性を上げることが出来ます。

注意点

2019年11月現在、InternetExplorerには対応していません。ブラウザへの対応状況はJavaScriptのドキュメントからご確認くださいませ。