Hatena::ブログ(Diary)

oct inaodu

 | 

2006-12-29

brazil2006-12-29

Deferredチェーン、非同期処理の逐次実行


MochiKit.Async.Deferredは、「現時点ではまた利用できない値」を扱うためのクラスです。


以下のように、コールバックを並べ、イベントを発火させると、各々の返り値が次のコールバックへ渡され実行されていきます。

function increment(value){
  alert(value);
  return value+1;
}

var d = new Deferred();
d.addCallback(increment); // alert(1)
d.addCallback(increment); // alert(2)
d.addCallback(increment); // alert(3)
d.callback(1);

この時、コールバックは以下のようにチェーンを形成しています。

(本当はエラーバックも合わせて一つのチェーンを形成しているのですが、これはまたいつか。)



コールバック処理の中で、Deferredのインスタンスを返すと、元のDeferredはポーズされ(pausedがtrueになる)、返されたDeferredオブジェクトに自分への通知をセットして、処理の終了を待ちます。

各コールバックがDeferredオブジェクトを返すと、以下のようにDeferredのチェーンが形成されることになります。



チェーンに組み込まれた各子供のDeferredオブジェクトは、chainedがtrueになり、新たにコールバックを追加することはできません。


以下は、reduceで0から4までを合算するサンプルです。

ループで瞬間的に一気に処理されます。


alert(
  reduce(function(num, memo){
    return num + memo;
  }, range(5), 0)
) // alert(10)

Deferredチェーンを使うと、ゆっくり実行することができます。


function deferredReduce(fn, iterable, initial){
  return reduce(function(d, value){
    return d.addBoth(fn, value);
  }, iterable, succeed(initial))
}

deferredReduce(function(num, memo){
  return wait(1, num + memo);
}, range(5), 0).addCallback(alert);  // alert(10)

1秒ずつのウェイトを空け、5秒後に10がアラートされます。

succeedは、予めコールバックしてあるDeferredを返します。

(この返り値の保持の部分が分かりづらいため、ここもまたいつか。)


関連リンク

今回のエントリはループで予めリストを形成していますが、こちらはゆっくりとした末尾再帰のように繰り返しを行っています。


リファレンス。一部、翻訳中です。

mopemopemopemope 2006/12/29 10:18 Deferredの元ネタも参考までに・・・・
http://www.akadav.org/twistedhowto/defer.html

brazilbrazil 2006/12/29 10:26 ぐはっ、知らなかったすけー。
ありがとござーす。
よわったなぁ、これ連載ものだったのに、あっちで十分にわかりやすいなぁ。

スパム対策のためのダミーです。もし見えても何も入力しないでください
ゲスト


画像認証

 |