2008年 01月 25日

JSDeferred の parallel が直接繋げられない理由

http://void.heteml.jp/blog/archives/2008/01/asdeferred.html ASDeferred !

parallel に直接つなげられない理由をとりあえず書いておきます。(ASDeferred での回避法はちゃんと読んでない><)

まずそもそも

next(function ..).
wait(1).
next(function ..);

みたいなときの wait(1) は

next(function ..).
next(function () {
    return wait(1);
}).
next(function ..);

を簡単に書くためだけにあります。でもこの二つには決定的な違いがあって、それは wait(..) の引数の評価タイミングです。wait みたいに引数がいつ評価してもかわらないようなのならいいのですが、parallel みたいなのだと困ります。(wait でも、変数を書いて、非同期にその値を書きかえる、っていう場合は同じように問題でてきます)

next(function () {
	alert(0);
	return wait(3).next(function () {
		alert(1);
	});
}).
next(function () {
	return parallel({
		foo: wait(1).next(function () { alert(2) }),
		bar: wait(2).next(function () { alert(3) })
	});
}).
next(function (results) {
	alert(4);
});

これは正しく 0, 1, 2, 3, 4 と表示されますが、

Deferred.register("parallel", parallel);

next(function () {
	alert(0);
	return wait(3).next(function () {
		alert(1);
	});
}).
parallel({
	foo: wait(1).next(function () { alert(2) }),
	bar: wait(2).next(function () { alert(3) })
}).
next(function (results) {
	alert(4);
});

これは parallel の引数の wait(1) と wait(2) が、最初の next() とかと同時に評価されるので、順がくずれ 0, 2, 3, 1 になります。(4 もよばれないけど、あとから継続をセットしてもよばないせい。変えようか迷ってるけど変えてない)


でもって、あんまり深く考えず、next().wait().next() みたいに書くのはあくまで速記法だから parallel はなくてイイヤーってのが今の状態です><

ちなみに call() の速記版がないのは、もともと prototype.call があるので名前に困ってつけてないだけです (この二つは全然ちがうものです)。