ECMAScript 7 で提案されている機能として async / await があります。簡単に言うと Promise を使った関数を簡潔に書くことのできる新しい文法です。

自分が知るかぎりでは C# 5.0 が最初に実装した、非同期プログラミングのための機能です。 ES6 すらまだ確定していないのに少し気が早い気もしますが Babel (旧 6to5 ) の experimental な機能として使えるみたいなので試してみました。

必要な知識

  • npm
  • ECMAScript 6 の Promise

必要なものをインストール

babel をインストールしておきます。またコンパイルされた JavaScript は babel-runtime が必要なのでそれもインストールしておきます。

$ npm install -g babel
$ npm install babel-runtime

非同期にカウントアップ

実際に簡単な例を作ってみました。1秒ごとに1から10までコンソールに表示するプログラムです。

const delay = t => new Promise(resolve => setTimeout(resolve, t));

async function countUp() {
    console.log('start');
    for (var i = 1; i <= 10; i++) {
        await delay(1000);
        console.log(i);
    }
    console.log('end');
}

console.log('before');
countUp().then(() => {
    console.log('after');
});

delay は与えられた時間だけ待つ Promise を返す関数です。

async function というのがキーワードで function の前に async をつけることで、その関数の内側で await が使えるようになります。

関数の中で await delay(1000) と書かれた部分で一旦処理が止まって、1秒後そこから処理が再開されます。 await に渡す値は Promise です。 countUp が返すのは Promise になります。

実行する

これを実行するには、コンパイルする必要がありますが、 babel-node を使うと変換して node で実行するところまでやってくれます。 experimental な機能なので -r--experimental がオプションとして必要です。

$ babel-node -r a.js

実行すると10秒かけて、次のように表示されます。

before
start
0
1
2
3
4
5
6
7
8
9
end
after

コンパイルする

コンパイルだけしたい場合の、オプションの指定方法は幾つかあります。

1つは CLI のオプションとして渡すことです。 -e で experimental な機能が有効になり -i runtime でジェネレータの実装を babel-runtime に任せます。

$ babel --out out.js -e -i runtime a.js

out.js を見ると async function がいろいろ変換されているのがわかります。

もう1つは .babelrc に指定する方法です。

{
  "experimental": true
}

コンパイル時に自動でこの設定が読み込まれます。

$ babel --out out.js -i runtime a.js

今後とか

async / await を使うと、 Promise を直接使うよりかなり簡潔に(特にループがかかわる場合)書けます。

この文法はまだ議論の途中なので、変更されたり、そもそもなかったことにされたりする可能性はあるので、使う場合はかなり気を使う必要があります。

ただし、自分の手元で簡単に Promise 周りの機能を試してみたい場合なんかには便利なはずです。用法用量を守って正しくお使いください。

まとめ

  • ES7 に async / await が提案されている
  • Babel に experimental な機能としてすでに実装されている
  • 実際のプロダクトで使うのはまだ早いけれど、便利に使える場面もあるはず