Search code examples
javascriptcometlong-polling

Sending messages to server with Comet long-polling


What's the best way to send data from client to server?

The example code I'm using is from How do I implement basic "Long Polling"?


Solution

  • Yes, just use up the second connection to the server. This is what most frameworks do, including iirc the Bayeux protocol. If you find out you actually need that second connection, worry about it then.

    Here's some long-polling code modified from my link above:

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

    What Moishe was talking about with the queue is that js doesn't guarantee that xhrs will be received in the order that you dispatched them. The messages won't be lost (or at least they haven't been in my tests), and this isn't a specific long-polling issue, but something to consider whenever you use xhr to send.

    So here's the queue code:

    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();
    };
    

    Two things to note. First, there's a fair bit of lag if you're sending many messages and the queue is filling up. It's better to find a way to send the entire queue each time, rather than piece by piece. One way to do this is to convert the messages into a JSON array, and decode on the server.

    Second, if there's an error sending the message, then you've lost the message. There needs to be a bit of code that will either push the failed message back onto the queue, or not remove it until there's success.