2011-09-25 107 views
2

我需要实现事件队列(=服务器上的更新)。新的事件将被添加到用户时改变所述滑块这个队列,按下按钮等。每个事件将包含以下属性:如何实现事件队列?

  1. 装置ID(动作将被应用到该设备的服务器上)
  2. 操作(设置,获取等)
  3. 值(value,应该在行动中使用)

新的事件应该有在年底增加。但是,如果已经有相同设备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移动,可能是它可以帮助我来简化这些队列创建?

回答

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) 
+0

谢谢,马丁。这几乎是我正在寻找的。只需要一个改变 - 事件应该从'doAPICall'的队列中删除,而不是提前(因为我需要等待它的回复,所以我在那里调用服务器)。 –

+0

那么您可以将事件从callAPIQueue队列中移动到doAPICall,并且应该按照您的意愿进行操作。 –

2

如果你期待一个短期事件队列,然后@马丁的解决方案是合适的。他的解决方案的时间复杂度是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);    
    } 
}