how does long polling work javascript?

前端 未结 7 1212
傲寒
傲寒 2020-12-08 11:41

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 th

相关标签:
7条回答
  • 2020-12-08 11:52

    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.

    0 讨论(0)
  • 2020-12-08 11:52

    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;
    
    }
    
    0 讨论(0)
  • 2020-12-08 11:55

    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.
    0 讨论(0)
  • 2020-12-08 11:57

    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.

    0 讨论(0)
  • 2020-12-08 12:02

    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); }});
    
    0 讨论(0)
  • 2020-12-08 12:03

    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.

    0 讨论(0)
提交回复
热议问题