请求数据分类:
- XMLHttpRequest(XHR)
- Dynamic script tag insertion 动态脚本注入
- iframes
- Comet
- Multipart XHR
这里主要讲述XHR
动态脚本注入
Multipart XHR
##1. XMLHttpRequest
Get
请求:
var url = '/data.php';
var params = [
'id=123',
'limit=20'
];
var req = new XMLHttpRequest();
req.onreadystatechange = function(){
if (req.readyState == 3){ //正在`流`数据 接受到部分信息,但不是所有
var data_now = req.responseText;
...
}
if (req.readyState === 4){
var reponse_headers = req.getAllReponseHeaders();//获取响应头信息
var data =req.reponseText; //获取数据
...
}
req.open('GET',url+'?' +params.join('&'),true);
req.setRequestHeader('X-Requested-With','XMLHttpRequest')//设置请求头信息.
req.send(null);//发送请求
}
Post请求
function xhr_post(url,params,callback){
var req =XMLHttpRequest();
req.onerror = function(){
setTimeout(function(){
xhr_post(url,params,callback);
},1000);
}
req.onreadystatechange = function(){
if(req.readyState ==4){
if (callback && typeof callback === 'function'){
callback();
}
}
};
req.open('POST',url,true);
req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
req.setRequestHeader('Contetn-Length',params.length);
req.send(params.join('&'));
}
注意点
XHR
不能从外域请求数据.- 低版本IE不支持
流
,和readyState为3
GET
请求不改变服务器数据,只作请求数据(幂等行为),这样这个GET会被缓存起来(也是一些BUG引发的原因),当URL长度超过2048时,建议使用POST,具体建议参考RESTful
- 一个POST请求至少发送两个数据包,一个装在头信息,另一个装在POST正文.而
GET
只发送一次.
能兼容IE的XHR写法
function create_XHR_object(){
var msxml_progid = [
'MSXML2.XMLHTTP.6.0',
'MSXML3.XMLHTTP',
'Microsoft.XMLHTTP', //不支持readyStatue 3
'MSXML2.XMLHTTP.3.0', //不支持readyStatue 3
];
var req ;
try {
req =new XMLHttpRequest();
}catch(e){
for (var i=0,len=msxml_progid.length;i<len;++i){
try{
req = new ActiveXObject(msxml_progid[i]);
break;
}catch(e2) {}
}
}finally{
return req;
}
}
##2. 动态脚本注入
特点:
- 能跨域请求
- 不能设置请求头
- 只能采用
GET
请求 - 不能设置请求超时
- 必须等所有数据都返回了,才可访问它们.
- 响应消息作为标签源码,外部的
js
必须是可执行javascript
代码,不能使用纯XML和JSON,必须封装在一个回调函数中. - 你使用外域的JSON,无法控制请求.容易有安全问题,例如JSONP漏洞(http://blog.knownsec.com/2015/03/jsonp_security_technic/)
外部文件lib.js
json_callback({"status" : 1});
本地javascript
var script_element = document.createElement('script');
script_element.src = "http://any-domain.com/javascript/lib.js";
document.getElementByTagName('head')[0].appendChild(script_element);
//回调函数,名字与外域的可执行`javascript`方法名一样,当外域js加载完成后,会执行json_callback(json_string)方法;
function json_callback(json_string){
var data = eval('('+json_string+')');
}
本地通过创建和外域.js的方法同名而实现回调.
但是调用在声明之前,为何可以?.
可以详细看第二章 :数据读取
.
##3. Multipart XHR
Multipart XHR
基于XHR,
只不过是把多个XHR
封装成一个XHR
而已.
但是性能可以快4~10倍.
具体实现代码可参考.http://techfoolery.com/mxhr/
使用建议.
- 页面包含了大量其他地方用不到的资源.
- 无需从缓存读数据,除非重载页面
##4. Beacons
和动态脚本注入类似
var url = '/status_tracker.php';
var params = [
'step=2',
'time=1248219291',
];
(new Image()).src = url + '?' + params.join('&');
//需要获取返回信息
var beacon = new Image();
beacon.src = url + '?' + params.join('&');
//这里假设服务器会返回图片,设定返回图片宽度为1为正确,2为错误.
beacon.onload = function (){
if(this.width == 1){
//成功
}else if (this.width ==2 ){
//失败,重新发送操作.
}
}
注意事项
- 当不用服务器返回数据时,服务器应该返回一个204状态码,阻止客户端继续等待不会到来的消息正文.
- 这也是和
GET
一样收url长度限制的 - 这个是给服务器回传消息的最佳方式,性能消耗很小.
- 服务器的错误完全影响不到客户端.
##5. JSON
- 数组JSON和对象集的JSON,前者下载和解析速度会比较快.
- 在使用动态脚本注入的时候,外域JSON数据建议封装在
parseJSON(JSON数据)里.
- XHR和动态脚本注入的效率基本一致.(小数据集),大数据动态脚本会比较快.因为不用解析JSON字符串.
##总结
- XHR技术比较安全,但解析比较慢,因为传递的是字符串.
- 动态注入脚本就不安全,但是不用解析.并且可以请求外域.
- Multipart XHR 可以很好的解决要很多HTTP连接问题.但不能缓存
- 减少请求数,合并javascript和css