3

を実行$(element).on('customevent',function(){});すると、 をバインドするすべての要素customeventもトリガーされます。これはおおよそ Pub/Sub として機能し、順序や優先度はないようです。私がやりたいことは、独自のコールバック キューを実装することですが、優先度を調整できます (Wordpress のように、フックの優先度を設定できます)。したがって、数値が大きいほど優先度が高くなり、数値 0 は一般的で最後に実行されます。

と の例を考える$(element).on_priority(10, 'customevent', function(){});$(element).on_priority(0, 'customevent', function(){});10優先度は同じものを 最初に実行し、優先度イベントcustomeventの実行をキャンセルする場合とキャンセルしない場合があります。0

どうすればそれを実装できますか? コールバックの流れを視覚化しようとするとうまくいきません

これまでのところ、私は次のように考えていました。

  • すべてのコールバック名が設定された「グローバル」(クロージャ内) オブジェクトを保持します。
  • コールバックの各メンバー内で、すべての優先度を含むオブジェクト。
var callbacks = {
  'customevent': {},
  'customevent2': {
    0: [{element: $element, fn: function(), data:{}}, {element: $element, fn: function(), data:{}}],
   10: [{element: $element, fn: function(), data:{}}],
   20: [{element: $element, fn: function(), data:{}}]
  }
};

正しい方向ですか?パフォーマンスに関しては、それほどヒットするべきではありません。問題は、オブジェクトを何度も繰り返すことです。これの問題は、以前に設定したイベントの登録を解除したり、各優先度内のコールバック配列の順序を設定 (または並べ替え) できないことです。

4

1 に答える 1

4

独自のオブジェクトにカプセル化できるコールバック オブジェクトの配列をお勧めします。オブジェクトには、追加、削除、および実行のメソッドがあります。追加、特定のコールバックを優先順に追加します。Remove は、コールバックを見つけて削除します。Execute は、各コールバックを優先順に呼び出しますが、いずれかのコールバックが を返す場合、それ以上のコールバックの実行を停止しますfalse

コールバックは配列内でソートされた順序で保持されるため、優先順位に従ってコールバックをトラバースするのは簡単です (配列の最初から最後まで移動するだけです)。

function sortedCallbacks() {
    this.list = [];
}

sortedCallbacks.prototype = {
    // add callback to the list
    add: function(fn, priority, data) {
        var list = this.list;
        var callbackObj = {fn: fn, priority: priority, data: data};

        for (var i = 0; i < list.length; i++) {
            // if our new priority is greater, then insert it here
            if (priority > list[i].priority) {
                list.splice(i, 0, callbackObj);
                return;
            }
        }
        // if the list was either empty or no priorities in the list were less than
        // the new priority, then just add this onto the end of the list
        list.push(callbackObj);
    },
    // remove callback from the list
    remove: function(fn, priority) {
        var list = this.list;
        for (var i = 0; i < list.length; i++) {
            if (list[i].fn === fn && list[i].priority === priority) {
                list.splice(i, 1);
                return;
            }
        }
    },
    // change priority or data or both
    change: function(fn, oldPriority, newPriority, data) {
        this.remove(fn, oldPriority);
        this.add(fn, newPriority, data);
    }
    // execute callbacks in order
    execute: function(/* args for callback passed here */) {
        // execute in priority order
        var list = this.list, retVal, args;
        for (var i = 0; i < list.length; i++) {
            args = [].slice.call(arguments, 0);
            // add the data for this callback to any arguments that were passed to execute
            args.unshift(list[i].data);
            retVal = list[i].fn.apply(this, args);
            // if callback returns false, then stop further callback execution
            if (retVal === false) {
                return;
            }
        }        
    }
};

使用例:

// create callbacks object and add some callbacks to it
var callbacks = new sortedCallbacks();
callbacks.add(fn1, 4, "whatever");
callbacks.add(fn2, 9, "hello");
callbacks.add(fn8, -1, "nothing");

// execute the callbacks and pass them each a value
callbacks.execute(elem.value)
于 2013-03-13T06:22:08.993 に答える