setTimeoutまたはsetIntervalの実装方法に関係なく、かなり効率的であるはずの1つのアイデアがあります。将来、N個の異なる時間にN個のイベントがスケジュールされている場合は、オブジェクトの配列を作成します。各オブジェクトには、イベントの期限となる時間のプロパティと、イベントの種類(コールバックまたは一部)を示すプロパティがあります。他の識別子)。最初にその配列をtimeプロパティで並べ替えて、次回がイベントの先頭になり、最も遠い時刻が最後になるようにします。
次に、アレイの前面を見て、そのイベントまでの時間を計算しsetTimeout()
、その期間を実行します。火災が発生したら、setTimeout()
配列の先頭を確認し、時間に達したすべてのイベントを処理します。イベントを処理した後、次の発生をスケジュールする必要がある場合は、将来発生する時間を計算し、配列を最初から最後まで歩き、その後にあるイベントを見つけて、そのイベントの直前に挿入します。 (配列をソートされた順序に保つため)。何も見つからない場合は、最後に挿入します。時間に達した配列の先頭からすべてのイベントを処理した後、配列の先頭にあるイベントまでのデルタ時間を計算し、setTimeout()
その間隔で新しいイベントを発行します。
ここにいくつかの擬似コードがあります:
function orderedQueue() {
this.list = [];
}
orderedQueue.prototype = {
add: function(time, callback) {
var item = {}, added = false;
item.time = time;
item.cb = callback;
for (var i = this.list.length - 1; i >= 0; i--) {
if (time > this.list[i].time) {
// insert after the i item
this.list.splice(i + 1, 0, item);
added = true;
break;
}
}
// if no item was after this item,
// then put this on the front of the array
if (!added) {
this.list.unshift(item);
}
},
addDelta(delta, callback) {
var now = new Date().getTime();
this.add(now + delta, callback);
},
waitNext: function() {
// assumes this.list is properly sorted by time
var now = new Date().getTime();
var self = this;
if (this.list.length > 0) {
// set a timer for the first item in the list
setTimeout(function() {
self.process();
}, this.list[0].time - now);
}
},
process: function() {
var now,item;
// call all callbacks who's time has been reached
while (this.list.length) {
now = new Date().getTime();
if (this.list[0].time <= now) {
// remove front item from the list
item = this.list.shift();
// call the callback and pass it the queue
item.cb(this);
} else {
break;
}
}
// schedule the next item
this.waitNext();
}
}
そして、これが一般的にあなたがそれをどのように使うかです:
var q = new orderedQueue();
// put initial events in the queue
q.addDelta(100, f1);
q.addDelta(1000, f2);
q.addDelta(5000, f3);
q.addDelta(10000, f4);
q.addDelta(200, f5);
q.addDelta(100, f1);
q.addDelta(500, f1);
// start processing of queue events
q.waitNext();