我曾经在2011年写过一个关于ajax使用Streaming获取推送数据的文章:
https://www.queyang.com/blog/archives/54 让ajax更加完美——Ajax Streaming研究和使用
Ajax Streaming常用的场景:
- 你通过AJAX向服务器提交一个请求,服务器会在接下来一段时间(比如1分钟)向客户端推送一些执行的信息,这样可以实时的看到进度,而传统的方式只能等到服务器执行完毕才能知道结果。
- 通过ajax获取服务器上一些实时数据,却不想使用定时(比如间隔1秒)ajax不断的请求
- 不需要客户端向服务器反馈交互的服务器推送数据显示方式
当然,在html5中有websocket可以满足页面和服务器交互的操作,这个是ajax stream所做不到的。
之前那篇文章简单介绍了使用stream的原理,然而jQuery一直不支持,今天闲来写了一个扩展jQuery的插件,可以让jQuery直接支持使用,增加了一个 message 的参数,当收到内容当前的内容会存放在 jqXHR.currentResponseText 中并回调message方法执行(注意:老版本的IE浏览器不支持,若需要支持,得用那篇在2011年写的那个文章的模拟方法)
此扩展支持HTTP的分块协议,可以自动将分块的长度数据给自动过滤只保留正文部分,HTTP分块协议见: http://zh.wikipedia.org/wiki/分块传输编码
插件扩展
(function ($) {
var ajax = $.ajax;
$.ajax = function (options)
{
var jqXHR;
if ($.isFunction(options.message))
{
if ($.isFunction(options.xhr))
{
options._xhr = options.xhr;
}
options.xhr = function() {
try
{
var xmlhttp = $.isFunction(this._xhr)? this._xhr() : new XMLHttpRequest();
var self = this;
xmlhttp.streaming = {
oldResponseLength : 0
};
var hexdec = function (hex_string)
{
hex_string = (hex_string + '').replace(/[^a-f0-9]/gi, '');
return parseInt(hex_string, 16);
};
/**
* 将HTTP协议中定义分块大小的长度部分移除
*
* @see http://zh.wikipedia.org/wiki/%E5%88%86%E5%9D%97%E4%BC%A0%E8%BE%93%E7%BC%96%E7%A0%81
* @param data
* @returns string
*/
var format = function(data)
{
if (data==="0\r\n\r\n")return ''; //分块输出结束符
data = $.trim(data);
var d = data.indexOf("\r\n");
if (d)
{
var len = hexdec(data.substr(0, d));
if (len>0 && len + 2 + d == data.length)
{
data = data.substr(d+2);
}
}
return data;
};
xmlhttp.onreadystatechange = function()
{
if (this.readyState == 3)
{
var data = this.responseText;
if (this.streaming.oldResponseLength>0)
{
data = data.substr(this.streaming.oldResponseLength);
}
this.streaming.oldResponseLength = this.responseText.length;
data = format(data);
if (data.length>0)
{
jqXHR.currentResponseText = data;
self.message.call(self, jqXHR, 'stream');
}
}
};
return xmlhttp;
}catch(e){}
};
var obs = null;
if ($.isFunction(options.beforeSend))
{
obs = options.beforeSend;
}
options.beforeSend = function(xhr) {
jqXHR = xhr;
if (obs)return obs.apply(this, arguments);
};
}
return ajax(options);
}
})(jQuery);
var ajax = $.ajax;
$.ajax = function (options)
{
var jqXHR;
if ($.isFunction(options.message))
{
if ($.isFunction(options.xhr))
{
options._xhr = options.xhr;
}
options.xhr = function() {
try
{
var xmlhttp = $.isFunction(this._xhr)? this._xhr() : new XMLHttpRequest();
var self = this;
xmlhttp.streaming = {
oldResponseLength : 0
};
var hexdec = function (hex_string)
{
hex_string = (hex_string + '').replace(/[^a-f0-9]/gi, '');
return parseInt(hex_string, 16);
};
/**
* 将HTTP协议中定义分块大小的长度部分移除
*
* @see http://zh.wikipedia.org/wiki/%E5%88%86%E5%9D%97%E4%BC%A0%E8%BE%93%E7%BC%96%E7%A0%81
* @param data
* @returns string
*/
var format = function(data)
{
if (data==="0\r\n\r\n")return ''; //分块输出结束符
data = $.trim(data);
var d = data.indexOf("\r\n");
if (d)
{
var len = hexdec(data.substr(0, d));
if (len>0 && len + 2 + d == data.length)
{
data = data.substr(d+2);
}
}
return data;
};
xmlhttp.onreadystatechange = function()
{
if (this.readyState == 3)
{
var data = this.responseText;
if (this.streaming.oldResponseLength>0)
{
data = data.substr(this.streaming.oldResponseLength);
}
this.streaming.oldResponseLength = this.responseText.length;
data = format(data);
if (data.length>0)
{
jqXHR.currentResponseText = data;
self.message.call(self, jqXHR, 'stream');
}
}
};
return xmlhttp;
}catch(e){}
};
var obs = null;
if ($.isFunction(options.beforeSend))
{
obs = options.beforeSend;
}
options.beforeSend = function(xhr) {
jqXHR = xhr;
if (obs)return obs.apply(this, arguments);
};
}
return ajax(options);
}
})(jQuery);
使用方法:
$.ajax({ url: "test.php", complete: function(){
console.log('done');
}, message: function(xhr) {
// 当收到消息时调用
console.log(xhr.currentResponseText);
}});
console.log('done');
}, message: function(xhr) {
// 当收到消息时调用
console.log(xhr.currentResponseText);
}});
test.php 代码例子
你测试过吗
当然
不好用啊,结果是一次返回的
请问:这个插件怎么用?是要合并到jquery.js主文件吗?还是另外保存为一个新js文件来使用?