2009-07-10 130 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>