Deferred のメモ諸々
callback 関数が Deferred オブジェクトを戻した場合
Collection & Copy - Deferredチェーン、非同期処理の逐次実行
コールバック処理の中で、Deferredのインスタンスを返すと、元のDeferredはポーズされ(pausedがtrueになる)、返されたDeferredオブジェクトに自分への通知をセットして、処理の終了を待ちます。
Async.js 内の _fire 関数内で、戻り値が MochiKit.Async.Deferred だった場合の処理があった。
何に使えるかは、ちょっと置いといて、とりあえず試しに書いたコード。
var parent = partial(add_message, 'parent'); var child = partial(add_message, 'child'); var parent_make_child = compose(partial(make_child, child), parent); var d = succeed('start'); d.addCallback(parent); d.addCallback(parent); d.addCallback(parent_make_child); d.addCallback(parent); d.addCallback(parent); d.addCallback(parent_make_child); d.addCallback(parent); d.addCallback(parent); function add_message (message, target) { target += ' ' + message; alert(target); return target; } function make_child (child, target) { var d = wait(10, target); d.addCallback(child); d.addCallback(child); return d; }
へー。
DeferredList
複数の Deferred の callback を待つ Deferred の事。
例えば、下記のように、二つの Deferred オブジェクトが存在している場合・・・
var d1_callback = partial(increment, 'd1'); var d2_callback = partial(increment, 'd2'); var d1 = new Deferred(); d1.addCallback(d1_callback); d1.addCallback(d1_callback); d1.addCallback(d1_callback); var d2 = new Deferred(); d2.addCallback(d2_callback); d2.addCallback(d2_callback); d2.addCallback(d2_callback); function increment (msg, num) { print(msg + ' : ' + num); return num + 1; }
下記のように、DeferredList オブジェクトを作る事で、d1 と d2 の二つが callback を受け取るまで待ってから、処理を行う事ができる。
var dl = new DeferredList([d1, d2], false, false, false); dl.addCallback(partial(print_num, '<callback1>')); dl.addCallback(partial(print_num, '<callback2>')); function print_num (msg, results) { print(msg); map( function (result) { if (result[0] == true) { print('value = ' + result[1]); } else { print(result[1].message); } }, results ); return results; }
ここで、下記を実行すると・・・
d1.callback(0); d2.callback(10);
下記の通り、出力される。
d1 : 0 d1 : 1 d1 : 2 d2 : 10 d2 : 11 d2 : 12 <callback1> value = 3 value = 13 <callback2> value = 3 value = 13
下記を実行すると・・・
d1.callback(0);
d2.errback('error!!');
下記の通り、出力される。
d1 : 0 d1 : 1 d1 : 2 <callback1> value = 3 error!! <callback2> value = 3 error!!
第二引数に true を渡すと、管理している Deferred が一つでも callback を受け取ると処理を実行する。
例えば、下記のように DeferredList を作った場合・・・
var dl = new DeferredList([d1, d2], true, false, false); dl.addCallback(partial(print_num, '<callback1>')); dl.addCallback(partial(print_num, '<callback2>')); function print_num (msg, results) { print(msg); print( 'index = ' + results[0]); print( 'value = ' + results[1]); }
下記を実行すると・・・
d2.callback(10);
下記のように出力される。
d2 : 10 d2 : 11 d2 : 12 <callback1> index = 1 value = 13 <callback2> index = 1 value = 13
第三引数に true を渡すと、管理している Deferred が一つでも errback を受け取ると処理を実行する。
例えば、下記のように DeferredList を作った場合・・・
var dl = new DeferredList([d1, d2], false, true, false); dl.addErrback(error); function error (e) { print('message:' + e.message); return 0; }
下記を実行すると・・・
d1.errback('error!!');
下記のように出力される。
message:error
第四引数に true を渡すと、管理している Deferred に DeferredList が追加する errback が null を返すようになる。
DeferredList は new された時に、第一引数に渡された Deferred オブジェクト一つ一つに、自分の callback や errback を呼ぶ _cbDeferred 関数を callback と errback として追加する。
その、_cbDeferred が、errback として実行された際、戻り値として null を返す・・・と言う事。
例えば、下記のように DeferredList を作った場合・・・
var dl = new DeferredList([d1, d2], false, false, true); d1.addCallback(d1_callback); d2.addCallback(d2_callback); dl.addCallback(partial(print_num, 'callback0'));
下記を実行すると・・・
d1.callback(0);
d2.errback('error');
下記のように出力される。
d1 : 0 d1 : 1 d1 : 2 d1 : 3 <callback1> value = 3 error!! <callback2> value = 3 error!! d2 : null