Как реализовать очередь событий? - PullRequest
2 голосов
/ 25 сентября 2011

Мне нужно реализовать очередь событий (= обновления на сервере).Новые события будут добавляться в эту очередь, когда пользователь изменяет ползунок, нажимает кнопки и т. Д. Каждое событие будет содержать следующие свойства:

  1. идентификатор устройства (действие будет применено к этому устройству на сервере)
  2. действие (установить, получить и т. Д.)
  3. значение (значение, которое следует использовать в действии)

Новое событие должно быть добавлено вконец.Но если уже есть событие для того же идентификатора устройства и с тем же действием, то это событие должно быть обновлено с новым значением.Как мне это сделать?

Я написал следующее:

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 ]

2 голосов
/ 25 сентября 2011

Если вы ожидаете короткую очередь событий, то решение @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 голос
/ 25 сентября 2011

Во-первых, у вас должен быть только один массив, содержащий объект события, в противном случае вы действительно слишком усложняете его для себя.

затем просто зациклите события и посмотрите, не было ли уже одно из того же устройства / действиясуществует при добавлении нового события.

попробуйте сделать что-то вроде этого:

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)
...