您好我明白,在长轮询中,您可以长时间保持与服务器的连接打开,直到您从服务器获得响应,然后再次轮询并等待下一个响应。但是,我似乎不明白如何编码它。下面有这个代码使用长轮询,但我似乎没有得到它
(function poll(){
$.ajax({ url: "server", success: function(data){
//update page based on data
}, dataType: "json", complete: poll, timeout: 30000 });
})();
但是如何在这里保持连接。我知道一旦获得服务器的响应,就会再次触发“poll”功能。但是如何保持连接打开?
Edit1: - 如果有人也可以解释实际上超时会发生什么,那就太棒了
答案 0 :(得分:11)
客户端无法强制服务器保持连接打开。 服务器根本就没有关闭连接。服务器必须在某个时候说“就是这样,这里没有更多的内容,再见”。在长轮询中,服务器根本不会这样做,并让客户端等待更多数据,随着更新的进行,它会逐渐涓涓细流。这是长时间的轮询。
在客户端,可以在请求尚未完成时偶尔检查已收到的数据。这样,有时可以通过相同的开放连接从服务器发送数据。在您的情况下,这没有完成,success
回调只会在请求完成时触发。它基本上是一种廉价的长轮询形式,服务器使客户端等待事件,发送有关此事件的数据,然后关闭连接。客户端将其作为触发器,处理数据,然后重新连接到服务器以等待下一个事件。
答案 1 :(得分:7)
我认为令人困惑的是,讨论主要集中在客户端编程上。
长轮询不是严格意义上的客户端模式,但要求Web服务器保持连接打开。
背景:当某些事情发生或可用时,客户希望通过网络服务器得到通知,例如,让我知道新电子邮件何时到达,而我不必每隔几秒就回复一次。
答案 2 :(得分:3)
我当时想要做一些交错的数据结果,其中一些会马上回来,但最后几个结果可能会在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); }});
答案 3 :(得分:3)
根据要求,这里有一些伪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;
}
答案 4 :(得分:2)
您不会仅从该代码中看到它是如何工作的,因为与常规请求的实际差异是在服务器上完成的。
Javascript只是发出常规请求,但服务器不必立即响应请求。如果服务器没有任何值得返回的东西(即浏览器正在等待的更改尚未发生),则服务器只是等待以保持连接打开。
如果服务器上没有任何时间发生任何事情,客户端将超时并发出新请求,或者服务器可以选择返回空结果以保持流量。
答案 5 :(得分:1)
连接始终未打开。当从服务器收到响应并且服务器关闭连接时,它会自动关闭。在长轮询中,服务器不应立即发送回数据。在ajax complete
上(当服务器关闭连接时),新请求被发送到服务器,服务器再次打开一个新连接并开始等待新响应。
如前所述,长轮询过程不仅由客户端处理,而且主要由服务器端处理。而且不仅是服务器脚本(在PHP的情况下),而是服务器本身,它不会通过超时关闭“挂起的”连接。
FWIW,WebSockets使用与服务器端不断打开的连接,这样就可以在不关闭连接的情况下接收和发回数据。
答案 6 :(得分:1)
我想没有人能正确解释为什么我们在代码中需要 timeout 。来自jQuery Ajax文档:
设置请求的超时(以毫秒为单位)。这将覆盖使用$ .ajaxSetup()设置的任何全局超时。超时时间从$ .ajax调用点开始;如果其他几个请求正在进行且浏览器没有可用的连接,则可以在请求发送之前将其超时
超时选项确实不会延迟下一次执行X秒。它仅为当前呼叫设置最大超时。关于超时内容的好文章 - https://mashupweb.wordpress.com/2013/06/26/you-should-always-add-timeout-to-you-ajax-call-in-jquery/