向服务器请求数据
有5种常用技术用于向服务器请求数据:
XMLHttpRequest(XHR)
Dynamic script tag insertion 动态脚本注入
iframes
Comet
Multipart XHR
1.XHR
XHR是目前最常用的技术,它允许异步发送和接收数据。所有的主流浏览器对它都提供了完善的支持,而且它还能精确地控制发送请求和数据接收。你可以在请求中添加任何头信息和参数(包括GET和POST),并读取服务器返回的所有头信息,以及响应文本。例:
var url = '/data.php'; var params = ['id=12344','limit=20']; var req = new XMLHttpRequest(); req.onreadystatechange = function(){ if(req.readyState === 4){ var responseHeaders = req.getAllResponseHeaders();//获取响应头信息 var data = req.responseText;//获取数据 //数据处理 } } req.open('GET',url+'?'+params.join('&'),true); req.setRequestHeader('X-Requested-with','XMLHttpRequest');//设置请求头信息 req.send(null);//发送请求
通过监听readyState值等于3,你可以与正在传输中的服务器响应进行交互,可以通过readyState值等于3说明此时正在与服务器交互,响应信息还在传输过程中。这就是所谓的“流”,它是提升数据请求性能的强大工具:
req.onreadystatechange = function(){ if(req.readyState === 3){//接收到部分信息,但不是所有 var dataSoFar = req.responseText; ... } else if(req.readyState === 4){ var data = req.responseText; ... } }
当使用XHR请求数据时,你需要再POST和GET之间做出选择。对于那些不会改变服务器状态,只会获取数据的请求,应该使用GET。经过GET请求的数据会被缓存起来,如果需要多次请求同一数据的话,它会有助于提升性能。只有当请求的URL加上参数的长度接近或者超过2048个字符时,才应该用POST获取数据。这是因为IE限制URL长度,过长时将会导致请求的URL被截断。
2.动态脚本注入
这种技术克服了XHR的最大限制:它能跨域请求数据。这是一个Hack,你不需要实例化一个专用对象,而可使用Javascript创建一个新的脚本标签,并设置它的src属性为不同域的URL。
var scriptElement = document.createElement('script'); scriptElement.src = 'http://any-domain.com/javascript/lib.js'; document.getElementsByTagName('head')[0].appendChild(scriptElement);
与XHR相比,动态脚本注入提供的控制是有限的。你不能设置请求的头信息。参数传递也只能使用GET方法,而不是POST方法。不能设置请求的超时处理或重试;事实上,就算失败了也不一定知道。必须等待所有数据都已返回,才可以访问它们。不能访问请求的头信息,也不能把整个响应消息作为字符串来处理。
最后一点特别重要。因为响应消息作为脚本标签的源码,它必须是可执行的javascript代码。你不能使用纯XML、纯JSON或其他任何格式的数据,无论哪种格式,都必须封装在一个回调函数中。
var scriptElement = document.createElement('script'); scriptElement.src = 'http://any-domain.com/javascript/lib.js'; document.getElementsByTagName('head')[0].appendChild(scriptElement); function jsonCallback(jsonString){ var data = eval('+'+jsonString+')'); //处理数据... }
3.Multipart XHR(MXHR)
MXHR允许客户端只用一个HTTP请求就可以从服务器端向客户端传送多个资源。它通过在服务端将资源(CSS文件、HTML片段、Javascript代码或base64编码的图片)打包成一个由双方约定的字符串分割的长字符串并发送到客户端。然后用Javascript代码处理这个长字符串,并根据它的mime-type类型和传入的其他“头信息”解释出每个资源。例:
首先,一个用来获取多张图片的请求发送到服务器:
var req = new XMLHttpRequest(); req.open('GET','rollup_images.php',true); req.onreadystatechange = function(){ if(req.readyState == 4){ splitImages(req.responseText); } } req.send(null);
下一步,服务器读取图片并将它们转换为字符串。服务器读取了三张图片并把它们转换为base64编码的长字符串,返回给客户端。
一旦数据到达客户端,该数据由splitImages函数处理:
function splitImages(imagesString){ var imageData = imageString.split("\u0001"); var imageElement; for(var i=0,len = imageData.length;i<len;i++){ imageElement = document.createElement('img'); imageElement.src = 'data:image/jpeg;base64,'+imageData[i]; document.getElementById('container').appendChild(imageElement); } }