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
を返しても良い。不自然なルールがなくて気持ち良い。