how does long polling work javascript?
Asked Answered
L

7

19

Hi I understand that in long polling you keep the connection with the server open for long till you a get a response back from the server and then poll again and wait for the next response. However i dont seem to understand how to code it. There is this code below which uses long polling but I dont seem to get it

(function poll(){
$.ajax({ url: "server", success: function(data){
   //update page based on data

}, dataType: "json", complete: poll, timeout: 30000 });
})();

But how is the connection kept open here. I understand that "poll" function is fired again once the response from the server is got.But how is the connection kept open?

Edit1:- It would be great if someone can also explain what would timeout actually do here

Longer answered 1/9, 2013 at 17:13 Comment(5)
Maybe the connection is not kept open....Misadventure
how do you prevent the server from closing the connection. If the request is sent to the server, it will respond and then the conn will automatically be closedLonger
@itamecodes: You write your server so that it doesn't respond until it has data to respond with.Millimeter
possible duplicate of Simple "Long Polling" example code?Arguable
I think that this person got the example from techoctave.com/c7/posts/… which is an article that seems to make no sense. It gives almost the same example twice and says one is long polling when it isn't!Dortch
B
18

The client cannot force the server to keep the connection open. The server is simply not closing the connection. The server will have to say at some point "that's it, there's no more content here, bye". In long polling, the server simply never does so and keeps the client waiting for more data, which it trickles out little by little as updates come in. That's long polling.

On the client side it's possible to check occasionally for the data which has already been received, while the request has not finished. That way data can occasionally be sent from the server over the same open connection. In your case this is not being done, the success callback will only fire when the request has finished. It's basically a cheap form of long polling in which the server keeps the client waiting for an event, sends data about this event and then closes the connection. The client takes that as the trigger, processes the data, then reconnects to the server to wait for the next event.

Bledsoe answered 1/9, 2013 at 17:19 Comment(6)
I guess I get it now.. can you please share some skeleton server code for little more clarityLonger
@itamecodes An important thing: for the server side you need to set configuration for not closing the connection by the timeout.Entice
@itame A simple sample would be while (!($data = checkDatabaseForData())) sleep(1); echo $data; - It depends on what language you're working with server side, an evented system like node.js would be a lot more elegant than a sleep loop.Bledsoe
@Bledsoe I have a question on ` In long polling, the server simply never does so and keeps the client waiting for more data...` how server will sends the response in parts. For example browser send the request to server, now if server need to send multiple responses(R1,R2 etc) back . It has to aggregate all and then send it back to client and close the connection. Server can not send the partial response R1 to browser and keep the connection open to send further response R2. Is not it ?Veal
@Veal It can, if the client would occasionally check the data that it has already received. It's been a long time since I touched the intricacies of long polling though and am not sure of the practical implementation anymore. All modern browsers support better mechanisms anyway like sockets.Bledsoe
@Bledsoe "while (!($data = checkDatabaseForData())) sleep(1); echo $data;"- As mentioned in your previous comment as quoted above, I think, if there is no more data, then there will be an infinite loop (sleep for 1 sec and then check and so on...). If I am correct, then how to stop the server from looping infinitely(in case, client browser is closed or no more new data is available in server for a long time)?Audly
H
9

I think what is making this confusing to understand is that the discussion is focused on the client-side programming.

Long-polling is not strictly a client-side pattern, but requires the web server to keep the connection open.

Background: Client wants to be notified by web server when something occurs or is available, for example, let me know when a new email arrives without me having to go back and ask every few seconds.

  1. Client opens a connection to a specific URL on the web server.
  2. Server accepts connection, opens a socket and dispatches control to whatever server-side code handles this connection (say a servlet or jsp in java, or a route in RoR or node/express).
  3. Server code waits until the event or information is available. For example, when an email arrives, sees if any of the "waiting connections" are for the particular inbox. If they are, then respond with the appropriate data.
  4. Client receives data, does its thing, then starts another request to poll.
Holms answered 1/9, 2013 at 17:24 Comment(0)
O
3

I was looking to do something with staggered data results where some would come back right away but the last few results might come back 10-15 seconds later. I created a quick little jQuery hack but it's kinda doing what I want (still not sure if it makes sense to use it tho):

(function($) {
    if (typeof $ !== 'function') return;
    $.longPull = function(args) {
        var opts = $.extend({ method:'GET', onupdate:null, onerror:null, delimiter:'\n', timeout:0}, args || {});
        opts.index = 0;
        var req = $.ajaxSettings.xhr();
        req.open(opts.method, opts.url, true);
        req.timeout = opts.timeout;
        req.onabort = opts.onabort || null;
        req.onerror = opts.onerror || null;
        req.onloadstart = opts.onloadstart || null;
        req.onloadend = opts.onloadend || null;
        req.ontimeout = opts.ontimeout || null;
        req.onprogress = function(e) {
            try {
                var a = new String(e.srcElement.response).split(opts.delimiter);
                for(var i=opts.index; i<a.length; i++) {
                    try {
                        var data = JSON.parse(a[i]); // may not be complete
                        if (typeof opts.onupdate==='function') opts.onupdate(data, i);
                        opts.index = i + 1;
                    } catch(fx){}
                }
            }
            catch(e){}
        };
        req.send(opts.data || null);
    };
})(jQuery);

Largely untested but it seemed to do what you had in mind. I can think of all sorts of ways it could go wrong, though ;-)

$.longPull({ url: 'http://localhost:61873/Test', onupdate: function(data) { console.log(data); }});
Osy answered 12/2, 2014 at 22:36 Comment(0)
D
3

As requested, here is some pseudo NodeJS code:

function respond_to_client(res,session,cnt)
{
    //context: res is the object we use to respond to the client
    //session: just some info about the client, irrelevant here
    //cnt: initially 0

    //nothing to tell the client, let's long poll.
    if  (nothing_to_send(res,session)) 
    {
        if (cnt<MAX_LONG_POLL_TIME)
        {
            //call this function in 100 ms, increase the counter
            setTimeout(function(){respond_to_client(request_id,res,session,cnt+1)},100);
        }
        else
        {
            close_connection(res); 
            //Counter too high.
            //we have nothing to send and we kept the connection for too long,
            //close it. The client will open another.
        }
    }
    else 
    {
        send_what_we_have(res);
        close_connection(res);
        //the client will consume the data we sent, 
        //then quickly send another request.
    }

    return;

}
Digenesis answered 13/7, 2014 at 15:43 Comment(0)
Y
2

You don't see how it works from that code only, because the actual difference from a regular request is done on the server.

The Javascript just makes a regular request, but the server doesn't have to respond to the request immediately. If the server doesn't have anything worth returning (i.e. the change that the browser is waiting for hasn't happened yet), the server just waits which keeps the connection open.

If nothing happens on the server for some time, either the client side will time out and make a new request, or the server can choose to return an empty result just to keep the flow going.

Yarndyed answered 1/9, 2013 at 17:24 Comment(0)
E
1

The connection is not kept open all the time. It is closed automatically when the response is received from the server and server closes the connection. In long polling the server is not supposed to send back data immediately. On ajax complete (when server closes the connection) the new request is sent to the server, which opens a new connection again and starts to keep pending for new response.

As was mentioned, long polling process is handled not only by client side, but mainly by server side. And not only by server script (in case of PHP), but by server itself, which doesn't close the "hanged" connection by timeout.

FWIW, WebSockets use constantly opened connection with the server side, which makes possible to receive and send back the data without closing the connection.

Entice answered 1/9, 2013 at 17:15 Comment(2)
Then how is this code different from traditional polling. By the way i have not downvoted this answerLonger
@Longer traditional polling = AJAX Polling: The requested webpage executes javascript which requests a file from the server at regular intervals (e.g. 0.5 seconds). see -#11078357Abfarad
A
1

I guess no one properly explain why do we need timeout in the code. From jQuery Ajax docs:

Set a timeout (in milliseconds) for the request. This will override any global timeout set with $.ajaxSetup(). The timeout period starts at the point the $.ajax call is made; if several other requests are in progress and the browser has no connections available, it is possible for a request to time out before it can be sent

The timeout option indeed doesn't delay the next execution for X seconds. it only sets a maximum timeout for the current call. Good article about timeout stuff - https://mashupweb.wordpress.com/2013/06/26/you-should-always-add-timeout-to-you-ajax-call-in-jquery/

Abfarad answered 30/4, 2015 at 14:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.