跨浏览器实现“HTTP Streaming”(推送)AJAX模式

时间:2009-07-10 23:18:50

标签: javascript ajax streaming xmlhttprequest comet

客户端从服务器请求网页。然后Clent要求进行额外的计算;服务器执行一系列计算并在可用时立即发送部分结果(文本格式,每行包含单独的完整项目)。客户端使用服务器提供的信息更新网页(使用JavaScript和DOM)。

这似乎符合Ajaxpatterns网站的HTTP Streamingcurrent版本)模式。

问题是如何以跨浏览器(浏览器不可知)的方式进行,最好不使用JavaScript框架,或使用像jQuery这样的轻量级框架。

问题始于以跨浏览器方式生成XMLHttpRequest,但我认为主要项目并非所有浏览器都onreadystatechange正确实现onreadystatechange;并非所有浏览器都会在每个服务器刷新上调用onreadystatechange事件(BTW。如何在CGI脚本中强制刷新服务器(在Perl中)?)。 Ajaxpatterns上的示例代码通过使用计时器处理此问题;如果我检测到来自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; } 的部分响应,我应该放弃计时器解决方案吗?


已添加11-08-2009

当前解决方案:
我使用以下函数来创建XMLHttpRequest对象:

setInterval

如果我要使用一些(最好是轻量级)JavaScript框架,比如jQuery,如果用户选择不安装jQuery,我希望有后备。

我使用以下代码启动AJAX;使用onreadystatechange是因为某些浏览器仅在服务器关闭连接(可能需要长达数十秒)之后调用function startProcess(dataUrl) { http = createRequestObject(); http.open('get', dataUrl); http.onreadystatechange = handleResponse; http.send(null); pollTimer = setInterval(handleResponse, 1000); } ,而不是在服务器刷新数据(大约每秒或更多次)之后立即调用handleResponse

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

{{1}}函数是最复杂的函数,但它的草图如下所示。可以做得更好吗?如何使用一些轻量级JavaScript框架(如jQuery)?

{{1}}

2 个答案:

答案 0 :(得分:2)

实际上,您链接的解决方案根本不是AJAX。他们称之为HTTP Streaming,但它基本上只是长轮询。

在他们链接的示例中,您可以使用firebug轻松地看到自己。打开网络面板 - 没有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>

答案 1 :(得分:0)

我会看看轨道上的

他们根据配置和浏览器嗅探使用了几种彗星传输实现。

请参阅http://orbited.org/svn/orbited/trunk/daemon/orbited/static/Orbited.js

并寻找“Orbited.CometTransports”

后端实现必须匹配一些不同的传输,因此请查看服务器端的轨道。