2014-05-03 Promise で async ライクな機能をつくった
bouzuya/promise-async-exampleをつくった。README.md にも書いたのだけれど、これは Promise の練習プロジェクト。何をしているのかを順に説明していく。
最近は Promise をコールバックの代替として使っている。完全に置き換わることはないだろうけど、少なくとも jQuery の Deferred の類は言語機能として提供される Promise に置き換えられると考えて、その準備として試している感じ。
しかし、Promise を使っていると、順次実行がやりづらいときがある。具体的な例を挙げると [1, 2, 3] に対して、それぞれ非同期の f に適用するのだけれど、それぞれを並列ではなく順次実行してほしいときがある。要するに caolan/async の mapSeries がほしくなる。並列実行は Promise.all を使えば簡単にできるのだけれど、順次実行はちょうど良い関数は提供されていない。
Promise でもおなじことをできるはずなのだけれど、考える時間がもったいないからと async をインストールしたりしていて、それはあんまりだと感じたので、今回の練習プロジェクトをつくって、今後は Promise 一本でやろうと思っている。
練習プロジェクトの中身を説明。
まず eachSeries を書いてみた。Promise.all でやると並列実行されることを確認して、then を数珠つなぎに書けば順次実行できることを確認して、reduce を使って可変なものに対応できるようにして、最後に汎用化する。
次に mapSeries を書いてみた。eachSeries で戻り値を保持すれば良いだけなので、そんなに難しくない。愚直だけど、results にまとめて返す。
おまけで waterfall を書いてみた。waterfall は順次実行で前の結果を次に渡す。これも簡単。
ちなみに上記、三つをまとめたものはここ。たぶん、都度書けば良いレベルだと思うので、パッケージにはしていない。
async より優れている点として引数の callback の位置を気にしなくて良い。一個引数を増やしたから動かない、なんてことがない。単純に結果を返しても、非同期なら Promise を返しても良い。不自然なルールがなくて気持ち良い。