XMLHttpRequest是一个浏览器接口Q得Javascript可以q行HTTP(S)通信?/p>
最早,微Y在IE 5引进了这个接口。因为它太有用,其他览器也模仿部v了,ajax操作因此得以诞生?/p>
但是Q这个接口一直没有标准化Q每家浏览器的实现或多或有点不同。HTML 5的概念Ş成后QW(xu)3C开始考虑标准化这个接口?008q?月,提ZXMLHttpRequest Level 2 草案?/p>
q个XMLHttpRequest的新版本Q提Z很多有用的新功能Q将大大推动互联|革新。本文就对这个新版本q行详细介绍?/p>
一、老版本的XMLHttpRequest对象
在介l新版本之前Q我们先回顾一下老版本的用法?/p>
首先Q新Z个XMLHttpRequest的实例?/p>
var xhr = new XMLHttpRequest();
然后Q向q程L发出一个HTTPh?/p>
xhr.open('GET', 'example.php');
xhr.send();
接着Q就{待q程L做出回应。这旉要监控XMLHttpRequest对象的状态变化,指定回调函数?/p>
xhr.onreadystatechange = function(){
if ( xhr.readyState == 4 && xhr.status == 200 ) {
alert( xhr.responseText );
} else {
alert( xhr.statusText );
}
};
上面的代码包含了老版本XMLHttpRequest对象的主要属性:(x)
* xhr.readyStateQXMLHttpRequest对象的状态,{于4表示数据已经接收完毕?/p>
* xhr.statusQ服务器q回的状态码Q等?00表示一切正常?/p>
* xhr.responseTextQ服务器q回的文本数?/p>
* xhr.responseXMLQ服务器q回的XML格式的数?/p>
* xhr.statusTextQ服务器q回的状态文本?/p>
二、老版本的~点
老版本的XMLHttpRequest对象有以下几个缺点:(x)
* 只支持文本数据的传送,无法用来d和上传二q制文g?/p>
* 传送和接收数据Ӟ没有q度信息Q只能提C有没有完成?/p>
* 受到"同域限制"QSame Origin PolicyQ,只能向同一域名的服务器h数据?/p>
三、新版本的功?/span>
新版本的XMLHttpRequest对象Q针对老版本的~点Q做Z大幅改进?/p>
* 可以讄HTTPh的时限?/p>
* 可以使用FormData对象理表单数据?/p>
* 可以上传文g?/p>
* 可以h不同域名下的数据Q跨域请求)?/p>
* 可以获取服务器端的二q制数据?/p>
* 可以获得数据传输的进度信息?/p>
下面Q我׃一介绍q些新功能?/p>
四、HTTPh的时?/span>
有时Qajax操作很耗时Q而且无法预知要花多少旉。如果网速很慢,用户可能要等很久?/p>
新版本的XMLHttpRequest对象Q增加了timeout属性,可以讄HTTPh的时限?/p>
xhr.timeout = 3000;
上面的语句,最长等待时间设?000毫秒。过了这个时限,p动停止HTTPh。与之配套的q有一个timeout事gQ用来指定回调函数?/p>
xhr.ontimeout = function(event){
alert('h时Q?);
}
目前QOpera、Firefox和IE 10支持该属性,IE 8和IE 9的这个属性属于XDomainRequest对象Q而Chrome和Safariq不支持?/p>
五、FormData对象
ajax操作往往用来传递表单数据。ؓ(f)了方便表单处理,HTML 5新增了一个FormData对象Q可以模拟表单?/p>
首先Q新Z个FormData对象?/p>
var formData = new FormData();
然后Qؓ(f)它添加表单项?/p>
formData.append('username', '张三');
formData.append('id', 123456);
最后,直接传送这个FormData对象。这与提交网表单的效果Q完全一栗?/p>
xhr.send(formData);
FormData对象也可以用来获取网表单的倹{?/p>
var form = document.getElementById('myform');
var formData = new FormData(form);
formData.append('secret', '123456'); // d一个表单项
xhr.open('POST', form.action);
xhr.send(formData);
六、上传文?/span>
新版XMLHttpRequest对象Q不仅可以发送文本信息,q可以上传文件?/p>
假定files是一?选择文g"的表单元素(input[type="file"]Q,我们它装入FormData对象?/p>
var formData = new FormData();
for (var i = 0; i < files.length;i++) {
formData.append('files[]', files[i]);
}
然后Q发送这个FormData对象?/p>
xhr.send(formData);
七、跨域资源共享(CORSQ?/span>
新版本的XMLHttpRequest对象Q可以向不同域名的服务器发出HTTPh。这叫做"跨域资源׃n"QCross-origin resource sharingQ简UCORSQ?/p>
使用"跨域资源׃n"的前提,是浏览器必须支持q个功能Q而且服务器端必须同意q种"跨域"。如果能够满上面的条gQ则代码的写法与不跨域的h完全一栗?/p>
xhr.open('GET', 'http://other.server/and/path/to/script');
目前Q除了IE 8和IE 9Q主浏览器都支持CORSQIE 10也将支持q个功能。服务器端的讄Q请参?a target="_blank" style="margin: 0px; padding: 0px; list-style-type: none; border: none; color: #112233;">《Server-Side Access Control?/a>?/p>
八、接收二q制数据Q方法AQ改写MIMETypeQ?/span>
老版本的XMLHttpRequest对象Q只能从服务器取回文本数据(否则它的名字׃用XML起首了)Q新版则可以取回二进制数据?/p>
q里又分成两U做法。较老的做法是改写数据的MIMETypeQ将服务器返回的二进制数据伪装成文本数据Qƈ且告诉浏览器q是用户自定义的字符集?/p>
xhr.overrideMimeType("text/plain; charset=x-user-defined");
然后Q用responseText属性接收服务器q回的二q制数据?/p>
var binStr = xhr.responseText;
׃q时Q浏览器把它当做文本数据Q所以还必须再一个个字节地还原成二进制数据?/p>
for (var i = 0, len = binStr.length; i < len; ++i) {
var c = binStr.charCodeAt(i);
var byte = c & 0xff;
}
最后一行的位运?c & 0xff"Q表C在每个字符的两个字节之中,只保留后一个字节,前一个字节扔掉。原因是览器解dW的时候,?x)把字符自?a target="_blank" style="margin: 0px; padding: 0px; list-style-type: none; border: none; color: #112233;">解读成Unicode?xF700-0xF7ff区段?/p>
八、接收二q制数据Q方法BQresponseType属性)
从服务器取回二进制数据,较新的方法是使用新增的responseType属性。如果服务器q回文本数据Q这个属性的值是"TEXT"Q这是默认倹{较新的览器还支持其他|也就是说Q可以接收其他格式的数据?/p>
你可以把responseType设ؓ(f)blobQ表C服务器传回的是二进制对象?/p>
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png');
xhr.responseType = 'blob';
接收数据的时候,用浏览器自带的Blob对象卛_?/p>
var blob = new Blob([xhr.response], {type: 'image/png'});
注意Q是dxhr.responseQ而不是xhr.responseText?/p>
你还可以responseType设ؓ(f)arraybufferQ把二进制数据装在一个数l里?/p>
var xhr = new XMLHttpRequest();
xhr.open('GET', '/path/to/image.png');
xhr.responseType = "arraybuffer";
接收数据的时候,需要遍历这个数l?/p>
var arrayBuffer = xhr.response;
if (arrayBuffer) {
var byteArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteArray.byteLength; i++) {
// do something
}
}
更详l的讨论Q请?a target="_blank" style="margin: 0px; padding: 0px; list-style-type: none; border: none; color: #112233;">Sending and Receiving Binary Data?/p>
?ji)、进度信?/span>
新版本的XMLHttpRequest对象Q传送数据的时候,有一个progress事gQ用来返回进度信息?/p>
它分成上传和下蝲两种情况。下载的progress事g属于XMLHttpRequest对象Q上传的progress事g属于XMLHttpRequest.upload对象?/p>
我们先定义progress事g的回调函数?/p>
xhr.onprogress = updateProgress;
xhr.upload.onprogress = updateProgress;
然后Q在回调函数里面Q用这个事件的一些属性?/p>
function updateProgress(event) {
if (event.lengthComputable) {
var percentComplete = event.loaded / event.total;
}
}
上面的代码中Qevent.total是需要传输的d节,event.loaded是已l传输的字节。如果event.lengthComputable不ؓ(f)真,则event.total{于0?/p>
与progress事g相关的,q有其他五个事gQ可以分别指定回调函敎ͼ(x)
* load事gQ传输成功完成?/p>
* abort事gQ传输被用户取消?/p>
* error事gQ传输中出现错误?/p>
* loadstart事gQ传输开始?/p>
* loadEnd事gQ传输结束,但是不知道成功还是失败?/p>
十、阅L?/span>
1. Introduction to XMLHttpRequest Level 2Q?新功能的l合介绍?/p>
2. New Tricks in XMLHttpRequest 2Q一些用法的介绍?/p>
3. Using XMLHttpRequestQ一些高U用法,主要针对Firefox览器?/p>
4. HTTP Access ControlQCORSlD?/p>
5. DOM access control using cross-origin resource sharingQCORS?UHTTP头信?/p>
6. Server-Side Access ControlQ服务器端CORS讄?/p>
7. Enable CORSQ服务端CORS讄?/p>
Q完Q?/p>