2013-09-01 70 views
6

您好,我明白,在長時間輪詢中,您會保持與服務器的連接長時間處於打開狀態,直到您從服務器獲得響應,然後再次輪詢並等待下一個響應。但是,我似乎不明白如何編碼。有以下代碼使用長輪詢,但我似乎並沒有得到它如何長期投票工作JavaScript?

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

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

但是,連接如何保持打開在這裏。我明白,一旦從服務器獲得響應,「poll」函數就會再次被觸發。但是連接如何保持打開?

EDIT1 - 這將是巨大的,如果有人也能解釋一下實際上會超時,在這裏做

+0

也許連接不保持開放.... – rene

+0

你如何防止服務器關閉連接。如果請求被髮送到服務器,它會響應,然後conn將自動關閉 – Rasmus

+0

@itamecodes:你編寫你的服務器,以便在它有數據要響應之前它不響應。的 – Eric

回答

7

客戶端無法強制服務器保持連接打開狀態。 服務器根本不關閉連接。服務器必須在某個時間點說「就是這樣,這裏沒有更多的內容,再見」。在長時間輪詢中,服務器根本不會這樣做,並且讓客戶端等待更多數據,隨着更新的進行,這些數據會一點一滴地涓流。這就是長時間的輪詢。

在客戶端可以偶爾檢查已收到的數據,而請求尚未完成。這樣數據偶爾可以通過同一個打開的連接從服務器發送。在你的情況下,這沒有完成,success回調將只在請求完成時觸發。它基本上是一種便宜的長輪詢形式,服務器讓客戶機等待事件,發送有關此事件的數據,然後關閉連接。客戶端將其作爲觸發器,處理數據,然後重新連接到服務器以等待下一個事件。

+0

我想我現在得到它..可以請你分享一些骨架服務器代碼更清晰 – Rasmus

+0

@itamecodes一個重要的事情:對於服務器端,您需要設置配置,以便在超時之前不關閉連接。 – VisioN

+1

@itame一個簡單的示例應該是while(!($ data = checkDatabaseForData()))sleep(1); echo $ data;' - 這取決於你在服務器端使用哪種語言,像node.js這樣的系統比'sleep'循環更優雅。 – deceze

1

連接未保持打開所有的時間。當從服務器收到響應並且服務器關閉連接時它會自動關閉。在長時間輪詢中,服務器不應該立即發回數據。在ajax complete(當服務器關閉連接時),新的請求被髮送到服務器,該服務器再次打開一個新的連接,並開始等待新的響應。

如前所述,長輪詢過程不僅由客戶端處理,而且主要由服務器端處理。並且不僅通過服務器腳本(在PHP的情況下),而且通過服務器本身,它不會通過超時關閉「掛起」連接。

FWIW,WebSockets使用與服務器端不斷打開的連接,這使得可以在不關閉連接的情況下接收和發回數據。

+0

那麼這段代碼與傳統的輪詢方式有何不同?順便說一句,我沒有downvoted這個答案 – Rasmus

+1

@itamecodes這*是傳統的「長輪詢」的方法。 – VisioN

+0

@Rasmus傳統輪詢= AJAX輪詢:請求的網頁執行javascript,以*常規*間隔(例如0.5秒)從服務器請求文件。請參閱-http://stackoverflow.com/questions/11077857/what-are-long-polling-websockets-server-sent-events-sse-and-comet –

6

我覺得讓人困惑的是,討論主要集中在客戶端編程上。

長輪詢不是嚴格的客戶端模式,但要求Web服務器保持連接打開。

背景:客戶希望在出現問題或有問題時通過網絡服務器通知客戶,例如,讓我知道新電子郵件何時到達,而不必每隔幾秒回去詢問一次。

  1. 客戶端打開與Web服務器上特定URL的連接。
  2. 服務器接受連接,打開一個套接字並向任何服務器端代碼處理此連接(例如,java中的servlet或jsp,或RoR或node/express中的路由)分派控制權。
  3. 服務器代碼將等待事件或信息可用。例如,當電子郵件到達時,看看是否有任何「等待連接」用於特定的收件箱。如果是,則用適當的數據作出迴應。
  4. 客戶端接收數據,做它的事情,然後啓動另一個請求輪詢。
2

您不明白它是如何工作的,因爲與常規請求的實際區別僅在服務器上完成。

的JavaScript只是讓一個普通的請求,但服務器沒有對請求立即響應。如果服務器沒有任何值得返回的東西(即瀏覽器正在等待的更改還沒有發生),服務器只是等待其中的連接打開。

如果沒有反應的服務器有一段時間了,無論是客戶端將超時,並作出新的請求,或者服務器可以選擇返回一個空的結果,只是爲了保持大流。

2

我一直在尋找做交錯的數據結果,其中有些人會回來馬上,但過去幾年的結果可能回來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); }}); 
2

按照要求,這裏是一些僞代碼的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; 

} 
1

我想沒有人好好解釋一下爲什麼我們在代碼中需要超時。來自jQuery Ajax文檔:

設置請求的超時時間(以毫秒爲單位)。這將覆蓋使用$ .ajaxSetup()設置的全局超時。超時時間從$ .ajax調用開始;如果其他幾個請求正在進行中,瀏覽器有沒有連接可用,有可能請求超時,纔可以被髮送

超時選項確實不耽誤X秒的一次執行。它僅爲當前呼叫設置最大超時時間。關於超時的東西好文章 - https://mashupweb.wordpress.com/2013/06/26/you-should-always-add-timeout-to-you-ajax-call-in-jquery/