2009-07-10 14 views
14

客戶端從服務器請求網頁。然後請求額外的計算完成;服務器執行一系列計算並在可用時立即發送部分結果(文本格式,每行包含單獨的完整項目)。客戶端使用服務器提供的信息更新網頁(使用JavaScript和DOM)。「HTTP流式傳輸」(推送)AJAX模式的跨瀏覽器實現

這似乎適合來自Ajaxpatterns網站的HTTP Streamingcurrent版本)模式。

問題是如何以跨瀏覽器(瀏覽器不可知)的方式做到這一點,最好不使用JavaScript框架,或使用像jQuery這樣的輕量級框架。

問題始於跨瀏覽器方式生成XMLHttpRequest,但我認爲主要內容是並非所有瀏覽器都能正確實現onreadystatechangeXMLHttpRequest;並非所有瀏覽器都在每個服務器上調用onreadystatechange事件flush(順便說一下,如何強制從CGI腳本(Perl中)刷新服務器?)。 Ajax模式上的示例代碼通過使用定時器來處理此問題;如果我檢測到來自onreadystatechange的部分響應,我應該放棄定時器解決方案嗎?


新增2009年11月8日

目前的解決方案:
我用下面的函數來創建XMLHttpRequest對象:

function createRequestObject() { 
     var ro; 
     if (window.XMLHttpRequest) { 
       ro = new XMLHttpRequest(); 
     } else { 
       ro = new ActiveXObject("Microsoft.XMLHTTP"); 
     } 
     if (!ro) 
       debug("Couldn't start XMLHttpRequest object"); 
     return ro; 
} 

如果我使用一些(最好是輕量級的)像jQuery這樣的JavaScript框架,如果用戶願意的話可以使用fallback選擇不安裝jQuery。

我使用下面的代碼啓動AJAX;使用setInterval是因爲某些瀏覽器只有在服務器關閉連接(可能需要幾十秒)後纔會調用onreadystatechange,而不是在服務器刷新數據(每秒鐘或更頻繁)後才立即調用onreadystatechange

function startProcess(dataUrl) { 
     http = createRequestObject(); 
     http.open('get', dataUrl); 
     http.onreadystatechange = handleResponse; 
     http.send(null); 

     pollTimer = setInterval(handleResponse, 1000); 
} 

handleResponse功能是最複雜的一個,但它的草圖如下所示。它可以做得更好嗎?如何使用一些輕量級的JavaScript框架(如jQuery)來完成?

function handleResponse() { 
    if (http.readyState != 4 && http.readyState != 3) 
     return; 
    if (http.readyState == 3 && http.status != 200) 
     return; 
    if (http.readyState == 4 && http.status != 200) { 
     clearInterval(pollTimer); 
     inProgress = false; 
    } 
    // In konqueror http.responseText is sometimes null here... 
    if (http.responseText === null) 
     return; 

    while (prevDataLength != http.responseText.length) { 
     if (http.readyState == 4 && prevDataLength == http.responseText.length) 
      break; 
     prevDataLength = http.responseText.length; 
     var response = http.responseText.substring(nextLine); 
     var lines = response.split('\n'); 
     nextLine = nextLine + response.lastIndexOf('\n') + 1; 
     if (response[response.length-1] != '\n') 
      lines.pop(); 

     for (var i = 0; i < lines.length; i++) { 
      // ... 
     } 
    } 

    if (http.readyState == 4 && prevDataLength == http.responseText.length) 
     clearInterval(pollTimer); 

    inProgress = false; 
} 
+0

您應該將該代碼示例添加爲回覆並將其標記爲正確的! – 2012-01-04 14:18:31

+4

「如果用戶選擇不安裝jQuery」? – Basic 2012-07-17 16:56:04

回答

2

實際上,鏈接到的解決方案根本不是AJAX。他們稱之爲HTTP Streaming,但它基本上只是長時間輪詢。

在他們鏈接的例子中,你可以很容易地看到螢火蟲。打開網絡面板 - 沒有XHR條目,但加載原始頁面僅需10秒鐘即可完成。這是因爲他們在幕後使用PHP來延遲HTML的輸出。這是長輪詢的實質 - HTTP連接保持打開狀態,並且發回的週期性HTML是javascript命令。

您可以選擇完全做輪詢在客戶端,雖然與的setTimeout()或setInterval的()

一個jQuery的例子

<script type="text/javascript"> 
    $(document).ready(function() 
    { 
    var ajaxInterval = setInterval(function() 
    { 
     $.getJSON(
     'some/servie/url.ext' 
     , { sample: "data" } 
     , function(response) 
      { 
      $('#output').append(response.whatever);   
      } 
    ); 
    }, 10000); 
    }); 
</script> 
相關問題