2011-09-25 75 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);    
    } 
}