使用Comet长轮询将消息发送到服务器

时间:2009-12-08 03:20:42

标签: javascript comet long-polling

将数据从客户端发送到服务器的最佳方法是什么?

我使用的示例代码来自How do I implement basic "Long Polling"?

3 个答案:

答案 0 :(得分:1)

只需使用XHR进行POST。

一个问题是在某些浏览器上,每个服务器只能有2个(或一些数量n个)并发XHR连接。您可以通过创建一个队列来解决这个问题,该队列允许您在当前XHR完成时发布所有等待的消息,然后填充新队列,直到该帖子完成,并且来回。

答案 1 :(得分:1)

将数据发送到服务器只是一个标准请求。 Xhr很好,或JSONP,不管你的船是什么漂浮。

不要被长轮询弄糊涂;长轮询仅作为从服务器发送到客户端的方式存在。从客户端向服务器发送数据是Web自成立以来的一直所用,并且只需要正常的Xhr请求。

答案 2 :(得分:1)

是的,只需用完第二次连接到服务器。这就是大多数框架所做的,包括Bayeux protocol的iirc。如果你发现你确实需要第二次连接,那么就要担心。

以下是我上面链接修改的一些长轮询代码:

var userid = Math.ceil(1000000*Math.random()).toString(16).toUpperCase();
var startLongpoll = function() {
    $.ajax({
        type:"POST", async:true, cache:false, timeout:0, 
        data: {userid: userid},
        success: function(data){
            _outCallback(data);
            setTimeout( startLongpoll, 10 );
        },
        error: function(xhr, textStatus, errorThrown){
            _errCallback(textStatus+" ("+errorThrown+")");
            setTimeout( startLongpoll, 5000 );
        },
    });
};
setTimeout(startLongpoll,10);

Moishe与队列讨论的是js不保证按照您发送的顺序接收xhrs。这些消息不会丢失(或者至少它们没有在我的测试中),这不是一个特定的长轮询问题,而是在您使用xhr发送时需要考虑的事项。

所以这是队列代码:

var queue = [];
var busy = false;
this.send = function(msg) {
    queue[queue.length] = msg;
    if (busy) return;
    busy=true;
    var s = function() {
        var m = queue.shift();
        $.ajax({
            type:"POST", async:true, cache:false, timeout: 5000,
            data: {userid:userid, msg:m},
            error: function(xhr, textStatus, errorThrown){
                _errCallback(textStatus + " (" + errorThrown + ")");
                if (queue.length>0) s(); else busy = false;
            },
            success: function(){
                if (queue.length>0) s(); else busy = false;
            }
        });
    }
    s();
};

有两点需要注意。首先,如果您发送许多消息并且队列正在填满,那么会有一些延迟。最好找到一种方法来每次发送整个队列,而不是一块一块地发送。一种方法是将消息转换为JSON数组,并在服务器上进行解码。

其次,如果发送消息时出错,那么您就丢失了消息。需要有一些代码可以将失败的消息推回到队列中,或者在成功之前不将其删除。