3

Watcher定期的に更新する必要のあるのセットがあるとしましょう。それらはそれぞれ異なるリフレッシュ間隔を持つ場合があります。Watcherいつでも数百のそのようなアイテムがあるかもしれません。任意の更新時間はWatcher、1秒から数分または数時間の範囲です。

どちらが良いですか?

  • それぞれに個別setTimeoutに使用してください。

  • setInterval毎秒関数を実行するを使用します。次に、関数は各Watcherチェックを循環して、更新が必要かどうかを確認します。

最初は、のネイティブコードの実装は、setTimeoutチェックを行うJS関数よりも効率的だと思いましたが、実際にsetTimeoutは、実装方法、各タイムアウトにかかる各ティックごとのオーバーヘッド、およびその数の問題です。タイムアウトのスケール。

私はこれをノードアプリケーションに求めているので、私が参照している特定のエンジンはV8ですが、他のエンジンの詳細も知っている人がいれば、それはすばらしいことです。

4

1 に答える 1

3

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();
于 2012-07-07T17:41:38.197 に答える