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

async function 式 を使用して async 関数を定義することもできます。

構文

async function name([param[, param[, ... param]]]) {
   statements
}

引数

name
関数名。
param
関数に渡す引数名。
statements
関数の本体を構成するステートメント。

返値

関数の中に含まれる、コードを実行する非同期関数を表す AsyncFunction オブジェクトを、resolved Promise の値と共に返します。rejectedの場合は補足されない例外を非同期関数から投げます。

説明

async 関数は、 await 式を含むことができます。 await 式は、async 関数の実行を一時停止し、 Promise の解決を待ちます。そして async 関数の実行を再開し、解決された値を返します。

キーワード await は、async 宣言された関数の中でのみ有効です. async 関数の外で使用した場合は SyntaxErrorとなります。

async/await 関数の目的は、 promise を同期的に使用する動作を簡素化し、 Promise のグループに対して何らかの動作を実行することです。 Promise が構造化コールバックに似ているのと同様に、 async/await はジェネレータと promise を組み合わせたものに似ています。

シンプルな例

var resolveAfter2Seconds = function() {
  console.log("starting slow promise");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(20);
      console.log("slow promise is done");
    }, 2000);
  });
};

var resolveAfter1Second = function() {
  console.log("starting fast promise");
  return new Promise(resolve => {
    setTimeout(function() {
      resolve(10);
      console.log("fast promise is done");
    }, 1000);
  });
};

var sequentialStart = async function() {
  console.log('==SEQUENTIAL START==');
  const slow = await resolveAfter2Seconds(); // If the value of the expression following the await operator is not a Promise, it's converted to a resolved Promise.
  const fast = await resolveAfter1Second();
  console.log(slow);
  console.log(fast);
}

var concurrentStart = async function() {
  console.log('==CONCURRENT START with await==');
  const slow = resolveAfter2Seconds(); // starts timer immediately
  const fast = resolveAfter1Second();

  console.log(await slow);
  console.log(await fast); // waits for slow to finish, even though fast is already done!
}

var stillSerial = function() {
  console.log('==CONCURRENT START with Promise.all==');
  Promise.all([resolveAfter2Seconds(), resolveAfter1Second()]).then(([slow, fast]) => {
    console.log(slow);
    console.log(fast);
  });
}

var parallel = function() {
  console.log('==PARALLEL with Promise.then==');
  resolveAfter2Seconds().then((message)=>console.log(message)); // in this case could be simply written as console.log(resolveAfter2Seconds());
  resolveAfter1Second().then((message)=>console.log(message));
}

sequentialStart(); // takes 2+1 seconds in total
// wait above to finish
setTimeout(concurrentStart, 4000); // takes 2 seconds in total
// wait again
setTimeout(stillSerial, 7000); // same as before
// wait again
setTimeout(parallel, 10000); // trully parallel

await を Promise.allと混同しないでください

add1 では、1つ目の await によって2秒間待機し、2つ目の await によってさらに2秒間待機します。2つ目のタイマーは、1つ目のタイマーが起動している間は作成されません。add2 では、両方のタイマーが作成され、両方とも待機します。タイマーは同時に実行されているため、4秒間ではなく2秒間で resolve されます。しかし、両方の await の呼び出しは、並列処理ではなく、依然として逐次処理となります。これは、自動的に Promise.all が適用されるわけではないためです。もし、並列した2つ以上の promise で await を実行したい場合は、Promise.all を使い続けなければなりません。

promise チェーンをasync function で 書き換える

promise を返す API は promise チェーンで解決され、関数を複数の部品に分割できます。次のコードを想定してください。:

function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch(e => {
      return downloadFallbackData(url)  // returns a promise
    })
    .then(v => {
      return processDataInWorker(v); // returns a promise
    });
}

次のように 1 つの async 関数に書き直すことができます。

async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url); 
  } catch(e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}

上記の例では、 return ステートメント上に await ステートメントがないことに注目してください。なぜなら、async function の返値は暗黙的に Promise.resolve でラップされているからです。

仕様

仕様 ステータス コメント
ECMAScript Latest Draft (ECMA-262)
async function の定義
ドラフト ES2017 における最初の定義。
ECMAScript 2017 (ECMA-262)
async function の定義
標準  

ブラウザー実装状況

機能ChromeEdgeFirefoxInternet ExplorerOperaSafari
基本対応55 あり52 なし4210.1
機能Android webviewChrome for AndroidEdge mobileFirefox for AndroidOpera AndroidiOS SafariSamsung Internet
基本対応 あり55 あり524210.16.0

1. From version 7.0.0: this feature is behind the --harmony runtime flag.

関連情報

ドキュメントのタグと貢献者

このページの貢献者: segayuu, isdh, 96beniko, jgs, H1Gdev, mfuji09, yoshioms1, YuichiNukiyama
最終更新者: segayuu,