Ajax Streaming是什么,可以起到什么作用?或许我给你举个例子你就会明白了,并且会喜欢上它
比如通过ajax请求一个安装脚本,此脚本可能需要执行1分钟,传统的ajax只有在页面执行完毕后才会得到执行情况,那么怎么可以让页面实时知道服务器上执行的状态呢?此时,Ajax Streaming就发挥作用了,可以帮你实现输出每个步骤的详细信息。
在服务器上,可通过特殊的处理,将每一个执行的步骤推送到浏览器。
这样就可以输出类似下面的信息了:
执行初始化成功…
开始执行步骤一
步骤一执行成功
步骤二开始
步骤二结束
…
全部执行完毕
PHP代码示例:
if (ob_get_level() == 0) ob_start();
// echo str_pad("", 1000);ob_flush();flush(); //兼容IE的堵塞,否则IE下只有执行完毕才会显示
for ($i = 0; $i<10; $i++)
{
echo "<br> Line to show.";
echo str_pad('',4096)."\n";
ob_flush();
flush();
sleep(1);
}
echo "Done.";
ob_end_flush();
上面的代码取自 http://php.net/manual/zh/function.flush.php
注意,nginx + php-fpm 模式需要在 nginx 的配置里加入
的配置
上面这样做后,大部分浏览器都可支持,但是,若此请求是在ajax中,则被称为Ajax Streaming,然后目前,经我测试Firefox,Chrome,Safari等都已支持,而IE不支持,看到有人说IE8支持,但我测试下来也是不支持的,所以在IE里需要寻求别的解决的方案,比如通过框架的方式是可以实现的。
在支持Ajax Streaming的浏览器中,不需要做特别的处理,每当浏览器收到新数据后,都会运行XMLHttpRequest的onreadystatechange方法,且XMLHttpRequest的状态readyState=3
例如:
xmlhttp.XMLHttpRequest = function(){
if (xmlhttp.readyState==3){
alert(xmlhttp.responseText);
}else if (xmlhttp.readyState==4){
alert('ok');
}
}
你会发现,当readyState==3的时候会被多此运行。
IE里只会执行1次,所以我采用了iframe的实现。普通的iframe会让浏览器产生一个loading进度条,这让人很不爽,所以采用了 http://infrequently.org/2006/02/what-else-is-burried-down-in-the-depths-of-googles-amazing-javascript/ 的方案。
通过创建一个new ActiveXObject(“htmlfile”);再特殊处理就可以不产生那个讨厌的加载进度了。
下面是我写的一个整合的代码,通过它完全模拟出了一个xmlhttp,
// 构造一个虚拟的xmlhttp对象
this.xmlhttp = {
responseXML: null,
responseText: '',
responseType: null,
response: '',
status: 0,
readyState: 0,
method: 'POST',
open: function(method, url) {
this.method = method;
var newurl = [];
if (url.indexOf('#') != -1) {
newurl = url.split('#');
}
else {
newurl = [url];
}
if (newurl[0].indexOf('?') == -1) {
newurl[0] += '?_ajax=true';
}
else {
newurl[0] += '&_ajax=true';
}
url = newurl.join('#');
this.url = url;
this.ifrDiv.innerHTML = '<iframe id="myqee_ajax_iframe" onload="alert(888)" name="myqee_ajax_iframe"></iframe><form id="myqee_ajax_fram" target="myqee_ajax_iframe" action="' + url + '" method="POST"></form>';
var objframe = this.obj.getElementById('myqee_ajax_iframe');
var getdata = function() {
if (objframe.readyState == 'loadinng') {
if (self.xmlhttp.readyState == 0) {
self.xmlhttp.readyState = 1;
self.xmlhttp.onreadystatechange();
}
}
else if (objframe.readyState == 'interactive') {
if (self.xmlhttp.readyState == 0) {
self.xmlhttp.readyState = 1;
self.xmlhttp.onreadystatechange();
}
if (self.xmlhttp.readyState == 1) {
self.xmlhttp.readyState = 2;
self.xmlhttp.onreadystatechange();
}
if (self.xmlhttp.readyState == 2) {
self.xmlhttp.readyState = 3;
}
if (self.xmlhttp.response != objframe.contentWindow.document.body.innerHTML) {
self.xmlhttp.response = self.xmlhttp.responseText = objframe.contentWindow.document.body.innerHTML;
self.xmlhttp.onreadystatechange();
}
}
else if (objframe.readyState == 'complete') {
clearInterval(runtime);
runtime = null;
if (self.xmlhttp.response != objframe.contentWindow.document.body.innerHTML) {
self.xmlhttp.response = self.xmlhttp.responseText = objframe.contentWindow.document.body.innerHTML;
self.xmlhttp.onreadystatechange();
}
self.xmlhttp.readyState = 4;
self.xmlhttp.status = 200;
self.xmlhttp.onreadystatechange();
}
};
var runtime = setInterval(getdata, 10);
},
send: function(data) {
if (this.method == 'GET') {
//GET方式最简单了
this.obj.getElementById('myqee_ajax_iframe').src = this.url;
}
else {
var newdata = data.split('&');
var html = '';
for (var i = 0; i < newdata.length; i++) {
var index = newdata[i].indexOf('=');
var k = decodeURIComponent(newdata[i].substr(0, index));
var v = decodeURIComponent(newdata[i].substr(index + 1));
html += '<textarea name="' + k.replace(/"/g, '"') + '">' + v.replace(/</g, '<') + '</textarea>' + "\n";
}
this.obj.getElementById('myqee_ajax_fram').innerHTML = html;
this.obj.getElementById('myqee_ajax_fram').submit();
//构造出一个表单提交
}
},
obj: new ActiveXObject("htmlfile")
};
this.xmlhttp.obj.open();
this.xmlhttp.obj.write("<html>");
this.xmlhttp.obj.write("</html>");
this.xmlhttp.obj.close();
this.xmlhttp.ifrDiv = this.xmlhttp.obj.createElement("div");
this.xmlhttp.obj.appendChild(this.xmlhttp.ifrDiv);
看得不是很明白,一直用jq…背景好黑啊..
比较忙,blog没有加代码高亮功能~
ie8是可以支持ajax streaming的, 有个类似xhr的XDomainRequest对象可以使用, 而且还可以跨域
你说的这个我知道的,简单的研究了下感觉还不错,有机会去深入研究下