2

設定:

あるアプリケーションの 3 つの別々の部分で 3 つのイベントが発生するとします。このイベントは 2 つのコントローラーで処理する必要があります。アプリケーション ディスパッチャーは、アプリケーションのすべての部分からのイベントの送受信を担当し、このディスパッチャーには非同期イベント キューが必要です。

場合によっては、3 つのイベントのうちの 2 つが何らかの属性に沿って関連付けられていますが、同じ名前ではなく、1 つだけをコントローラーに渡す必要があり、もう 1 つを破棄する必要があります。

問題:

現在、イベントをコントローラーにバウンスするだけの「キュー」があります。一度に 1 つしかない場合、キュー内の 2 つのイベントを比較する方法がないため、これは役に立ちません。

では、イベントがキューにしばらく留まるようにするにはどうすればよいでしょうか? タイムアウト機能でうまくいくと思いますが、もっと良い方法はありますか?

当然のことながら、イベントを結合するというアイデアは Cocoa に触発されており、基本的には似たようなことをしようとしています。

4

2 に答える 2

2

私は Cocoa についてあまり知りませんが、イベントがアプリケーションにディスパッチされるまで (つまり、何らかの理由でアプリケーションがビジーである場合)、古いイベントを最新のイベントに置き換えると思います。特定のユースケースが何であるかはわかりませんが、イベントをレート制限したい場合は、次のsetTimeoutように使用します。

function Dispatcher(controllers) {
    this.controllers = controllers;
    this.events = [];
    this.nextController = 0;
}
Dispatcher.prototype = {
    _dispatch: function (i) {
        var ev = this.events.splice(i, 1);
        this.controllers[this.nextController].handle(ev);
        this.nextController = (this.nextController + 1) % this.controllers.length;
    },
    notify: function (ev) {
        var index = -1, self = this, replace;

        function similer(e, i) {
            if (e.type === ev.type) {
                index = i;
                return true;
            }
        }

        replace = this.events.some(similar);
        if (replace) {
            this.events[i] = ev;
        } else {
            // it's unique
            index = this.events.push(ev) - 1;
            setTimeout(function () {
                self._dispatch(index);
            }, 100);
        }
    }
};

notifyイベントで呼び出すだけで(typeプロパティまたは類似のものがあることを確認してください)、魔法を処理します。さまざまなタイプのイベントは、独自の で一意に処理されますsetTimeout

私はこのコードをテストしていないので、バグがある可能性があります。

于 2012-12-05T21:33:11.767 に答える
1

タイムアウト関数でうまくいくと思いますが、もっと良い方法はありますか?

いいえ、実際にはありません。

通常、setTimeout(..., 0)イベントが同じ実行ループでディスパッチされるかどうかを使用する方法があります。したがって、実装は次のようになります。

var eventQueue = [];
var handlerTimer = -1;
function fireEvent(event, params) {
    eventQueue.push([event, params]);
    window.clearTimeout(handlerTimer);
    handlerTimer = window.setTimeout(resolveQueue, 0);
}

function resolveQueue() {
    // process eventQueue and remove unwanted events...
    // then dispatch remaining events

    eventQueue = [];
}

異なる実行ループからのイベント(たとえば、mouseupやなどのネイティブイベントclick)を処理する必要がある場合は、0以外のタイムアウト値を使用する必要があります。正確な値は、イベントを蓄積する期間によって異なります。

于 2012-12-05T21:26:05.753 に答える