如何实现事件队列?

时间:2011-09-25 09:37:57

标签: javascript jquery-mobile queue

我需要实现事件队列(=服务器上的更新)。当用户更改滑块,按下按钮等时,新事件将添加到此队列中。每个事件将包含以下属性:

  1. 设备ID(该操作将应用于服务器上的该设备)
  2. 动作(设置,获取等)
  3. value(应在操作中使用的值)
  4. 最后应该在那里添加新事件。但是,如果已存在相同设备ID和相同操作的事件,则应使用新值更新此事件。我该怎么做?

    我起草了以下内容:

    var inCall = false;
    var queueArrayDevices = new Array();
    var queueArrayActions = new Array();
    var queueArrayValues = new Array();
    
    // add call to the queue, at the end
    function addAPICall(device, action, value){
        // should NOT add event here, if device and action already exists
        // should update the value instead
        queueArrayDevices.push(device);
        queueArrayAсtions.push(action);
        queueArrayValues.push(value);
    }
    
    function doAPICall(device, action, value){    
        inCall = true;
        // call server here
        // if not successful, we should add this item to the queue again
        inCall = false;
    }
    
    function callAPIQueue(){
        if(!inCall && queueArrayDevices.length > 0){
            device = queueArrayDevices.shift();
            action = queueArrayAсtions.shift();
            value = queueArrayValues.shift();
            doAPICall(device, action, value);        
        }
    }
    
    // start queue processing
    setInterval(callAPIQueue, 400);
    

    我使用jquery mobile,可能它可以帮助我简化这样的队列创建吗?

2 个答案:

答案 0 :(得分:2)

如果您期望短事件队列,那么@Martin的解决方案是合适的。他的解决方案的时间复杂度是O(n),其中n是队列长度,如果n很小,这是完美的。

如果您的队列可能会变长,那么您可能会考虑更快的方法,如下所示。队列由将唯一标识符(device_id,action)映射到值的映射表示。这提供了对现有属性的快速查找。时间复杂度降低到O(log n)。在Javascript中方便地实现地图是使用将(device_id,action)编码成唯一字符串的对象属性,例如, “DEVICE_ID#行动”。此外,属性被链接以提供先进/先出行为。

var Map = {
    // properties: "id#action": {value: value, next: property}
    first: "",
    last: "",
    empty: function() {return Map.first == "";},
    enque: function(device, action, value) {
        var k = device + "#" + action;
        if (k in Map) {
            Map[k].value = value;
        }
        else {
            Map[k] = {value: value, next: ""};
            if (Map.first == "") {
                Map.first = Map.last = k;
            }
            else {
                Map[Map.last].next = k;
                Map.last = k;
            }               
        }

    },
    deque: function() {
        var firstProp = Map.first;
        var key = firstProp.split("#");
        var value = Map[firstProp].value;
        Map.first = Map[firstProp].next;
        delete firstProp; // delete this property
        return {device: key[0], action: key[1], value: value};  
    }   
};

地图使用如下:

function addAPICall(device, action, value) {
    Map.enque(device, action, value);
}    
function callAPIQueue() {     
    if (!inCall && !Map.empty()) {     
        var event = Map.deque();         
        doAPICall(event.device, event.action, event.value);             
    } 
} 

答案 1 :(得分:1)

首先,你应该只有一个数组持有一个事件对象,否则你实际上已经过度复杂了。

接下来只是遍历事件并查看添加新事件时是否已存在相同的设备/操作之一。

尝试这样做:

var inCall = false;
var queue = [];

// add call to the queue, at the end
function addAPICall(device, action, value){
  var found=false;
  for(var i=0, event; event = queue[i]; i++) {
    if(event.action == action && event.device == device) {
      event.value = value;
      found = true;
      break;
    }
  }
  if(!found) {
    queue.push({device: device, action: action, value: value});
  }
}

function doAPICall(device, action, value){    
    inCall = true;
    // call server here
    // if not successful, we should add this item to the queue again
    inCall = false;
}

function callAPIQueue(){
    if(!inCall && queueArrayDevices.length > 0){
    var event = queue.shift();
        doAPICall(event.device, event.action, event.value);        
    }
}

// start queue processing
setInterval(callAPIQueue, 400)