跨浏览器实现与QUOT; HTTP流" (推)AJAX模式 [英] Cross-browser implementation of "HTTP Streaming" (push) AJAX pattern

查看:146
本文介绍了跨浏览器实现与QUOT; HTTP流" (推)AJAX模式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

从服务器的客户端请求的网页。克伦特然后请求额外的计算来进行;服务器将执行一系列的计算,一旦它们可将部分结果(文本格式,每行包含独立的全项)。使用由服务器提供的信息的客户端更新网页(使用JavaScript和DOM)。

这似乎符合 HTTP流(的当前版)模式从Ajaxpatterns网站。

现在的问题是如何做到这一点的跨浏览器(浏览器无关)的方式,preferably不使用JavaScript框架,或使用一些像jQuery的轻量级框架。

与产生XMLHtt prequest跨浏览器的方式的问题开始,但我认为主要的产品,并非所有的浏览器实现正确的onreadystatechange 从的 XMLHtt prequest ;并非所有浏览器叫的onreadystatechange 事件上的每个服务器刷新(BTW。如何从CGI脚本(在Perl内强制服务器刷新)?)。在Ajaxpatterns示例code处理这个使用定时器;我应该放弃计时解决方案,如果我发现从的onreadystatechange

部分缓解


补充2009年11月8日

当前的解决方案:
我用下面的函数来创建XMLHtt prequest对象:

 函数createRequestObject(){
        VAR RO;
        如果(window.XMLHtt prequest){
                RO =新XMLHtt prequest();
        } 其他 {
                RO =新的ActiveXObject(Microsoft.XMLHTTP);
        }
        如果(!RO)
                调试(无法启动XMLHtt prequest对象);
        返回RO;
}
 

如果我是用一些(preferably重量轻)像jQuery JavaScript框架,我想有回退,如果用户选择不安装jQuery的。

我用下面的code开始AJAX; 的setInterval 是因为有些浏览器调用的onreadystatechange 服务器关闭连接之后才(只要它可以为几十秒) ,而不是只要服务器刷新数据(周围的每一个第二或更多的时候)。

 函数startProcess(dataUrl){
        的http = createRequestObject();
        http.open('得到',dataUrl);
        http.onreadystatechange =用handleResponse;
        http.send(空);

        pollTimer = setInterval的(用handleResponse,1000);
}
 

用handleResponse 的功能是最复杂的,但它的草图看起来像下面这样。它可以做的更好?如何将它用做一些轻量级的JavaScript框架(像jQuery)?

 函数用handleResponse(){
    如果(http.readyState = 4和!&安培;!http.readyState = 3)
        返回;
    如果(http.readyState == 3&安培;&安培;!http.status = 200)
        返回;
    如果(http.readyState == 4和&安培;!http.status = 200){
        clearInterval(pollTimer);
        INPROGRESS = FALSE;
    }
    //在Konqueror http.responseText这里有时是空...
    如果(http.responseText ===空)
        返回;

    而(prevDataLength!= http.responseText.length){
        如果(http.readyState == 4和&安培; prevDataLength == http.responseText.length)
            打破;
        prevDataLength = http.responseText.length;
        VAR响应= http.responseText.substring(nextLine);
        VAR线= response.split('\ N');
        nextLine = nextLine + response.lastIndexOf('\ N')+ 1;
        如果(响应[response.length-1]!='\ N')
            lines.pop();

        对于(VAR I = 0; I< lines.length;我++){
            // ...
        }
    }

    如果(http.readyState == 4和&安培; prevDataLength == http.responseText.length)
        clearInterval(pollTimer);

    INPROGRESS = FALSE;
}
 

解决方案

您链接到该解决方案是不是AJAX可言,其实。他们称之为HTTP流,但它本质上只是长轮询。

在他们链接到的例子,你可以自己很容易看到萤火虫。打开网络面板 - 没有XHR的条目,但它需要短短的头发超过10秒加载原来的页面。这是因为他们使用的是幕后的PHP延迟HTML的输出。这是长轮询的本质 - HTTP连接保持打开状态,以及定期的HTML发送回是JavaScript命令

您可以选择完全做轮询在客户端,虽然与的setTimeout()或setInterval的()

一个jQuery的例子

 <脚本类型=文/ JavaScript的>
  $(文件)。就绪(函数()
  {
    VAR ajaxInterval =的setInterval(函数()
    {
      $ .getJSON(
        有些/役/ url.ext
        {示例:数据}
        ,函数(响应)
          {
            $('#输出)追加(response.whatever);
          }
      );
    },10000);
  });
< / SCRIPT>
 

Client request web page from server. Clent then requests for extra calculations to be done; server performs series of calculations and sends partial results as soon as they are available (text format, each line contains separate full item). Client updates web page (with JavaScript and DOM) using information provided by server.

This seems to fit HTTP Streaming (current version) pattern from Ajaxpatterns site.

The question is how to do it in cross-browser (browser agnostic) way, preferably without using JavaScript frameworks, or using some lightweight framework like jQuery.

The problem begins with generating XMLHttpRequest in cross-browser fashion, but I think the main item is that not all browsers implement correctly onreadystatechangefrom XMLHttpRequest; not all browsers call onreadystatechange event on each server flush (BTW. how to force server flush from within CGI script (in Perl)?). Example code on Ajaxpatterns deals with this by using timer; should I drop timer solution if I detect partial response from onreadystatechange?


Added 11-08-2009

Current solution:
I use the following function to create XMLHttpRequest object:

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

If I were to use some (preferably light-weight) JavaScript framework like jQuery, I'd like to have fallback if user chooses not to install jQuery.

I use the following code to start AJAX; setInterval is used because some browsers call onreadystatechange only after server closes connection (which can take as long as tens of seconds), and not as soon as server flushes data (around every second or more often).

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

        pollTimer = setInterval(handleResponse, 1000);
}

The handleResponse function is most complicated one, but the sketch of it looks like the following. Can it be done better? How it would be done using some lightweight JavaScript framework (like 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;
}

解决方案

The solution you linked to is not AJAX at all, actually. They call it HTTP Streaming but it's essentially just long polling.

In the example they link to, you can see for yourself quite easily with firebug. Turn on the Net panel - there are no XHR entries, but it takes just a hair over 10 seconds to load the original page. That's because they're using PHP behind the scenes to delay the output of the HTML. This is the essence of long polling - the HTTP connection stays open, and the periodic HTML sent back is javascript commands.

You can opt to do the polling completely on the client side, though, with setTimeout() or setInterval()

A jQuery example

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

这篇关于跨浏览器实现与QUOT; HTTP流&QUOT; (推)AJAX模式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆