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 な機能としてすでに実装されている
- 実際のプロダクトで使うのはまだ早いけれど、便利に使える場面もあるはず