IntervalDeferred

Deferredに登録した関数が次に実行されるまでの期間も設定できるようにしたものです。ldrの遅延描画的なことを実現してみたかったので。以下のような感じに使います。

var id = new IntervalDeferred();
id.add_action(function() {
  Hoge.update_item(0);
}, 500);
id.add_action(function() {
  Hoge.update_item(1);
}, 200);
id.fire();

var id = new IntervalDeferred(true);
id.add_action(function() {
  Hoge.update_item(0);
}, 500);
id.cancel();
id.add_action(function() {
  NeverHappend();
}, 200);

http://qouop.dyndns.org/htbsj/lib/IntervalDeferred.js
実装の主な部分はDeferredLock + callLater。

はてぶさ をjavascriptだけで作り直すついでにはてなブックマーク情報取得APIを使っていて、エントリー情報をすべて一度に処理せず、1エントリずつ処理する際に使ってます。ページ内の全エントリを処理し終わる前に前後移動のページャ操作が入った場合にcancel()しています。

2006-12-09追記

2006-12-03時点でのIntervalDeferred.js実装は以下の通りです。callLaterMSはミリ秒対応させたもの。

IntervalDeferred = function(immediately) {
  this.deferred_lock = new DeferredLock();
  this.immediately = immediately;
  this.actions = [];
  this.current_count = counter();
  this.last_deferred = null;
}

IntervalDeferred.prototype = {
  add_action: function(func, interval/* == 0*/) {
    var self = this;
    if (typeof(interval) == undefined || interval == null) {
      interval = 0;
    }
    var action = function() {
      func();
      return callLaterMS(interval, function() {
        self.deferred_lock.release();
        self.current_count();
      });
    };
    if (self.immediately) {
      self.last_deferred = self.deferred_lock.acquire().addCallback(action);
    }
    else {
      self.actions.push(action);
    }
  },

  fire: function() {
    var self = this;
    if (!self.immediately) {
      forEach(self.actions, function(action) {
        self.deferred_lock.acquire().addCallback(action);
      });
    }
  },

  cancel: function() {
    var self = this;
    self.last_deferred.cancel();
  }
};
bindMethods(IntervalDeferred);