长轮询是如何工作的javascript

how does long polling work javascript?

本文关键字:工作 javascript 何工作      更新时间:2023-09-26

嗨,我知道在长时间轮询中,您可以保持与服务器的连接打开很长时间,直到您从服务器收到响应,然后再次轮询并等待下一个响应。然而,我似乎不明白如何编码它。下面有一个代码使用长轮询,但我似乎没有得到它的

(function poll(){
$.ajax({ url: "server", success: function(data){
   //update page based on data
}, dataType: "json", complete: poll, timeout: 30000 });
})();

但这里的联系是如何保持开放的。我知道,一旦收到服务器的响应,"轮询"功能就会再次启动。但这种联系是如何保持开放的呢?

Edit1:-如果有人也能解释一下超时在这里实际会做什么,那就太好了。

客户端不能强迫服务器保持连接打开。服务器根本没有关闭连接。服务器将不得不在某个时候说"就这样,这里没有更多内容了,再见"。在长轮询中,服务器根本不会这样做,而是让客户端等待更多的数据,随着更新的到来,这些数据会一点一点地流出。这就是长轮询。

在客户端,当请求尚未完成时,可以偶尔检查已经接收到的数据。这样,偶尔可以通过相同的开放连接从服务器发送数据。在您的情况下,success回调只有在请求完成时才会触发。这基本上是一种廉价的长轮询形式,服务器让客户端等待事件,发送有关该事件的数据,然后关闭连接。客户端将其作为触发器,处理数据,然后重新连接到服务器以等待下一个事件。

我认为让人难以理解的是,讨论集中在客户端编程上。

长轮询并不是严格意义上的客户端模式,而是要求web服务器保持连接打开。

背景:客户希望在发生什么事情或有什么可用的时候得到网络服务器的通知,例如,当一封新的电子邮件到达时告诉我,而我不必每隔几秒钟就回去询问一次。

  1. 客户端打开与web服务器上特定URL的连接
  2. 服务器接受连接,打开套接字,并将控制分派给处理此连接的任何服务器端代码(比如java中的servlet或jsp,或者RoR或node/express中的路由)
  3. 服务器代码等待事件或信息可用。例如,当一封电子邮件到达时,查看是否有任何"等待连接"是针对特定收件箱的。如果是,则使用适当的数据进行响应
  4. 客户端接收数据,完成它的工作,然后启动另一个轮询请求

我想对交错的数据结果做点什么,有些结果会立即返回,但最后几个结果可能会在10-15秒后返回。我创建了一个快速的jQuery小破解,但它有点像我想做的(仍然不确定使用它是否有意义):

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

基本上未经测试,但它似乎做到了你的想法。不过,我能想出各种可能出错的方法;-)

$.longPull({ url: 'http://localhost:61873/Test', onupdate: function(data) { console.log(data); }});

根据请求,这里有一些伪NodeJS代码:

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

仅从代码中看不到它是如何工作的,因为与常规请求的实际区别是在服务器上完成的。

Javascript只是发出一个常规请求,但服务器不必立即响应请求。如果服务器没有任何值得返回的东西(即浏览器正在等待的更改尚未发生),服务器只会等待,从而保持连接打开。

如果服务器上在一段时间内没有发生任何事情,客户端将超时并发出新的请求,或者服务器可以选择返回一个空结果来保持流的运行。

连接不是一直保持打开状态。当从服务器收到响应并且服务器关闭连接时,它会自动关闭。在长轮询中,服务器不应该立即发回数据。在ajax complete上(当服务器关闭连接时),新的请求被发送到服务器,服务器再次打开一个新的连接,并开始等待新的响应。

如前所述,长轮询过程不仅由客户端处理,而且主要由服务器端处理。不仅通过服务器脚本(在PHP的情况下),还通过服务器本身,这不会在超时时关闭"挂起"连接。

FWIW,WebSockets使用与服务器端不断打开的连接,这使得在不关闭连接的情况下接收和发送回数据成为可能。

我想没有人能正确解释为什么我们在代码中需要超时。来自jQuery Ajax文档:

为请求设置超时(以毫秒为单位)。这将覆盖使用$.ajaxSetup()设置的任何全局超时。超时期从进行$.ajax调用时开始;如果其他几个请求正在进行中,而浏览器没有可用的连接,则请求可能会在发送之前超时

timeout选项确实不会将下一次执行延迟X秒。它只为当前调用设置最大超时。关于超时的好文章-https://mashupweb.wordpress.com/2013/06/26/you-should-always-add-timeout-to-you-ajax-call-in-jquery/