JavaScript: использование очереди для сетевого общения - PullRequest
5 голосов
/ 08 января 2012

Я работаю над проектом, в котором клиент должен иметь возможность общаться с сервером через WebSockets. Начиная с приложения, которое мы разрабатываем так, чтобы оно было очень отзывчивым на пользовательский ввод, мы решили позволить WebWorker осуществлять всю связь по сети, чтобы медленное соединение не могло прерывать графический интерфейс пользователя. Пока все отлично.

Теперь мы подумали об оптимизации, которая будет необходима, если сеть работает медленно и количество отправляемых сообщений велико. Поскольку большинство из этих сообщений будут только для синхронизации пользовательского интерфейса некоторых других клиентов, мы можем отбросить некоторые из них при необходимости. Но для этого нам нужна возможность выявлять ситуации, когда есть заторы.

Мы придумали идею очереди: каждое отправляемое сообщение помещается в очередь, и WebWorker делает только постоянные итерации по очереди и отправку всех найденных там сообщений. После этого мы можем позволить Рабочему действовать по-другому, если в очереди есть определенное количество элементов (то есть сообщения отправляются слишком медленно). Идея проста и понятна, однако реализация, похоже, не такова.

var ws;
var queue = new Array();

function processMessageQueue() {
    while(true)
        if(queue.length > 0) ws.send(queue.shift());
}

self.addEventListener('message', function(e) {
    var msg = e.data;
    switch(msg.type) {
        case 'SEND':
            queue.push(JSON.stringify(msg));
            break;
        case 'CREATE_WS':
            ws = new WebSocket(msg.wsurl);
            ws.onmessage = function(e) {
                self.postMessage(JSON.parse(e.data));
            }
            processMessageQueue();
    }
}, false);

Как видите, работник создает WebSocket, как только получает сообщение для этого. Затем он выполняет функцию processMessageQueue (), которая является циклом, который постоянно очищает очередь, отправляя их данные через WebSocket. Теперь моя проблема в том, что, похоже, нет возможности помещать сообщения в очередь. Это должно произойти, когда приходит сообщение типа «ОТПРАВИТЬ», но это не может сделать, поскольку работник слишком занят для обработки каких-либо событий. Таким образом, он может либо проходить по очереди, либо отправлять сообщения, но не оба.

Мне нужен способ как-то отправить данные в эту очередь. Если это не легко возможно, я хотел бы знать, может ли кто-нибудь придумать другой способ узнать, когда сообщения приходят быстрее, чем они отправляются. Есть намеки?

Заранее спасибо!

1 Ответ

2 голосов
/ 08 января 2012

Вы должны дать работнику время для обработки события onmessage. Выполнение while(true) займет все время обработки и не позволит выполнять какие-либо события.

Например, вы можете изменить его на

function processMessageQueue() {
    if(queue.length > 0) ws.send(queue.shift());
    setTimeout(processMessageQueue, 50);
}
...