如何在jQuery的帮助下创建回调优先队列

How to create a callback priority queue with the help of jQuery?

本文关键字:创建 回调 优先队列 帮助 jQuery      更新时间:2023-09-26

在执行$(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:{}}]
  }
};

方向正确吗?性能方面,它应该不会有太大的影响,问题是对象的迭代一次又一次。这样做的问题是,我将无法注销先前设置的事件或设置每个优先级

内的回调数组的顺序(甚至重新排序)。

我建议使用一个回调对象数组,您可以将其封装在自己的对象中。对象有添加、删除和执行的方法。按优先级顺序添加给定的回调。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)