エラーを throw した時の Deferred の処理順

Spider Monkey で下記のサンプルを実行すると・・・

var d = new Deferred();
d.addCallbacks(throw_error, partial(error, 'debug0'));
d.addCallback(increment);
d.addCallbacks(increment, partial(error, 'debug1'));
d.addCallback(increment);
d.addCallback(increment);
d.addCallback(throw_error);
d.addCallback(increment);
d.addCallbacks(increment, partial(error, 'debug2'));
d.addCallback(increment);
d.addErrback(partial(error, 'debug3'));
d.callback(1);

function increment (num) {
  print(num);
  return num + 1;
}

function error (message, e) {
  print(message + ':' + e.message);
  return 0;
}

function throw_error (num) {
  throw new GenericError('error!!');
}

下記のように出力される。

debug1:error!!
0
1
debug2:error!!
0

表にすると、こんな感じにチェーンが形成されている。

i call back error back
0 throw_error partial(error, 'debug0')
1 increment
2 increment partial(error, 'debug1')
3 increment
4 increment
5 throw_error
6 increment
7 increment partial(error, 'debug2')
8 increment
9 partial(error, 'debug3')

0 行目の throw_error でエラーが throw されて 2行目の、partial(error, 'debug1') が実行される。
そのまま、3 行目、4行目 の increment が実行される。
次に、5行目の throw_error でエラーが throw されて、7行目の、partial(error, 'debug2') が実行される。
最後に、8行目の increment が実行されて終わり。

「d.callback(1);」を「d.errback(new GenericError('error!!'));」に変更すると、下記のような出力となる。

debug0:error!!
0
1
2
3
debug2:error!!
0

error back のチェーンだけ実行し続けたい場合は、error back に登録されいてる関数内で、エラーを throw し続ければ良い。

うーん、我ながら、解り難い説明だ・・・。

参考書籍

WEB+DB PRESS Vol.37
Rediscover the JavaScript【最終回】MochiKitを極める! …Webプログラミング編……舘野祐一