动态载入脚本
这个技术的特点克服了XHR最大的缺点:跨域访问。使用如下:
varscriptElement=document.createElement('script');
scriptElement.src='http://any-domain.com/javascript/lib.js';
document.getElementsByTagName('head')[0].appendChild(scriptElement);
动态载入脚本不像XHR那样可以随意设置请求头部,参数只能通过GET发送,只有脚本从服务器完全返回以后你才能访问脚本。
由于这种方式的响应结果是可执行的JS代码,不需要特殊的处理和分析,因而性能十分可观。不过你仍然需要注意,使用这种方式时你对服务器完全没有控制,你无法获得脚本载入期间的信息。而且你也要意识到动态载入的脚本一旦加载完成,它就能够对本页面的数据内容进行修改、转发或者重定向,所以使用时需要格外小心。
更多信息可以看这里:http://book.51cto.com/art/200812/99672.htm
MulipartXHR
这个是以上Ajax请求数据几种方式中最新的技术。MXHR的特点是,只使用一个请求来从服务器将资源发送给客户端,只要组装好了不论是CSS文件、脚本文件、HTML片段还是base64编码的图片。客户端以字符串的形式接受,然后根据MIME类型和其它传输的信息来解析。
示例-使用一个请求下载多个图片资源:
varreq=newXMLHttpRequest();
req.open('GET','rollup_images.php',true);
req.onreadystatechange=function(){
if(req.readyState==4){
splitImages(req.responseText);
}
};
req.send(null);
首先请求页面,然后将响应数据利用方法解析。当然这需要服务器首先要将图片信息转化为base64编码的字符串,同时你需要指定一个连接符号,以便在客户端分割这些字符串。
假定分割符是unidcode编码的1
functionsplitImages(imageString){
varimageData=imageString.split("\u0001");
varimageElement;
for(vari=0,len=imageData.length;i<len;i++){
imageElement=document.createElement('img');
imageElement.src='data:image/jpeg;base64,'+imageData[i];
document.getElementById('container').appendChild(imageElement);
}
}
任何能够在JS中通过字符串处理的数据类型都可以使用这种方式传输。以下是几个常用函数:
functionhandleImageData(data,mimeType){
varimg=document.createElement('img');
img.src='data:'+mimeType+';base64,'+data;
returnimg;
}
functionhandleCss(data){
varstyle=document.createElement('style');
style.type='text/css';
varnode=document.createTextNode(data);
style.appendChild(node);
document.getElementsByTagName('head')[0].appendChild(style);
}
functionhandleJavaScript(data){
eval(data);
}
当MXHR传输的数据越来越庞大时,最好的方式是接受一部分数据以后立刻开始处理,而不是等待全部数据加载完成再处理。通过监听XHR的readyState3来处理。
varreq=newXMLHttpRequest();
vargetLatestPacketInterval,lastLength=0;
req.open('GET','rollup_images.php',true);
req.onreadystatechange=readyStateHandler;
req.send(null);
functionreadyStateHandler{
if(req.readyState===3&&getLatestPacketInterval===null){
//Startpolling.
getLatestPacketInterval=window.setInterval(function(){
getLatestPacket();
},15);
}
if(req.readyState===4){
//Stoppolling.
clearInterval(getLatestPacketInterval);
//Getthelastpacket.
getLatestPacket();
}
}
functiongetLatestPacket(){
varlength=req.responseText.length;
varpacket=req.responseText.substring(lastLength,length);
processPacket(packet);
lastLength=length;
}
一旦readyState3第一次触发,一个计时器启动。每隔15ms检测新数据,当找到一个事先约定的分隔符之后收集数据,然后处理这部分数据。
更完美的实现比较复杂但是值得研究,你可以看看这里:http://techfoolery.com/mxhr/
这个技术的缺点就是获取的数据你无法缓存,比如图片、CSS文件等;另外就是老版本的IE不支持监听readyState3,也不支持data:URLs。(IE8支持,IE6和IE7需要变通方法)
不过由于它的优点实在是吸引人,所以这些情况你最好使用MXHR:
1)如果这个页面包含很多其他页面不需要的资源,尤其是图片;
2)如果站点的每个页面的脚本或CSS都已经组装为一个独特的请求,亦即站点内跨页面访问没有共同的请求。
减少HTTP请求能够全面提升页面的性能,尤其是你需要传输100张图片,只用一个请求通常能为站点的用户体验带来质的飞跃。测试页面:http://techfoolery.com/mxhr/