http://www.ruanyifeng.com/blog/2012/09/xmlhttprequest_level_2.html

XMLHttpRequest是一个浏览器接口,使得Javascript可以进行HTTP(S)通信。

最早,微软在IE 5引进了这个接口。因为它太有用,其他浏览器也模仿部署了,ajax操作因此得以诞生。

但是,这个接口一直没有标准化,每家浏览器的实现或多或少有点不同。HTML 5的概念形成后,W3C开始考虑标准化这个接口。2008年2月,就提出了XMLHttpRequest Level 2 草案。

这个XMLHttpRequest的新版本,提出了很多有用的新功能,将大大推动互联网革新。本文就对这个新版本进行详细介绍。

一、老版本的XMLHttpRequest对象

在介绍新版本之前,我们先回顾一下老版本的用法。

首先,新建一个XMLHttpRequest的实例。

  var xhr = new XMLHttpRequest();

然后,向远程主机发出一个HTTP请求。

  xhr.open('GET', 'example.php');

  xhr.send();

接着,就等待远程主机做出回应。这时需要监控XMLHttpRequest对象的状态变化,指定回调函数。

  xhr.onreadystatechange = function(){

    if ( xhr.readyState == 4 && xhr.status == 200 ) {

      alert( xhr.responseText );

    } else {

      alert( xhr.statusText );

    }

  };

上面的代码包含了老版本XMLHttpRequest对象的主要属性:

  * xhr.readyState:XMLHttpRequest对象的状态,等于4表示数据已经接收完毕。

  * xhr.status:服务器返回的状态码,等于200表示一切正常。

  * xhr.responseText:服务器返回的文本数据

  * xhr.responseXML:服务器返回的XML格式的数据

  * xhr.statusText:服务器返回的状态文本。

二、老版本的缺点

老版本的XMLHttpRequest对象有以下几个缺点:

  * 只支持文本数据的传送,无法用来读取和上传二进制文件。

  * 传送和接收数据时,没有进度信息,只能提示有没有完成。

  * 受到"同域限制"(Same Origin Policy),只能向同一域名的服务器请求数据。

三、新版本的功能

新版本的XMLHttpRequest对象,针对老版本的缺点,做出了大幅改进。

  * 可以设置HTTP请求的时限。

  * 可以使用FormData对象管理表单数据。

  * 可以上传文件。

  * 可以请求不同域名下的数据(跨域请求)。

  * 可以获取服务器端的二进制数据。

  * 可以获得数据传输的进度信息。

下面,我就一一介绍这些新功能。

四、HTTP请求的时限

有时,ajax操作很耗时,而且无法预知要花多少时间。如果网速很慢,用户可能要等很久。

新版本的XMLHttpRequest对象,增加了timeout属性,可以设置HTTP请求的时限。

  xhr.timeout = 3000;

上面的语句,将最长等待时间设为3000毫秒。过了这个时限,就自动停止HTTP请求。与之配套的还有一个timeout事件,用来指定回调函数。

  xhr.ontimeout = function(event){

    alert('请求超时!');

  }

目前,Opera、Firefox和IE 10支持该属性,IE 8和IE 9的这个属性属于XDomainRequest对象,而Chrome和Safari还不支持。

五、FormData对象

ajax操作往往用来传递表单数据。为了方便表单处理,HTML 5新增了一个FormData对象,可以模拟表单。

首先,新建一个FormData对象。

  var formData = new FormData();

然后,为它添加表单项。

  formData.append('username', '张三');

  formData.append('id', 123456);

最后,直接传送这个FormData对象。这与提交网页表单的效果,完全一样。

  xhr.send(formData);

FormData对象也可以用来获取网页表单的值。

  var form = document.getElementById('myform');

  var formData = new FormData(form);

  formData.append('secret', '123456'); // 添加一个表单项

  xhr.open('POST', form.action);

  xhr.send(formData);

六、上传文件

新版XMLHttpRequest对象,不仅可以发送文本信息,还可以上传文件。

假定files是一个"选择文件"的表单元素(input[type="file"]),我们将它装入FormData对象。

  var formData = new FormData();

  for (var i = 0; i < files.length;i++) {

    formData.append('files[]', files[i]);

  }

然后,发送这个FormData对象。

  xhr.send(formData);

七、跨域资源共享(CORS)

新版本的XMLHttpRequest对象,可以向不同域名的服务器发出HTTP请求。这叫做"跨域资源共享"(Cross-origin resource sharing,简称CORS)。

使用"跨域资源共享"的前提,是浏览器必须支持这个功能,而且服务器端必须同意这种"跨域"。如果能够满足上面的条件,则代码的写法与不跨域的请求完全一样。

  xhr.open('GET', 'http://other.server/and/path/to/script');

目前,除了IE 8和IE 9,主流浏览器都支持CORS,IE 10也将支持这个功能。服务器端的设置,请参考《Server-Side Access Control》。

八、接收二进制数据(方法A:改写MIMEType)

老版本的XMLHttpRequest对象,只能从服务器取回文本数据(否则它的名字就不用XML起首了),新版则可以取回二进制数据。

这里又分成两种做法。较老的做法是改写数据的MIMEType,将服务器返回的二进制数据伪装成文本数据,并且告诉浏览器这是用户自定义的字符集。

  xhr.overrideMimeType("text/plain; charset=x-user-defined");

然后,用responseText属性接收服务器返回的二进制数据。

  var binStr = xhr.responseText;

由于这时,浏览器把它当做文本数据,所以还必须再一个个字节地还原成二进制数据。

  for (var i = 0, len = binStr.length; i < len; ++i) {

    var c = binStr.charCodeAt(i);

    var byte = c & 0xff;

  }

最后一行的位运算"c & 0xff",表示在每个字符的两个字节之中,只保留后一个字节,将前一个字节扔掉。原因是浏览器解读字符的时候,会把字符自动解读成Unicode的0xF700-0xF7ff区段。

八、接收二进制数据(方法B:responseType属性)

从服务器取回二进制数据,较新的方法是使用新增的responseType属性。如果服务器返回文本数据,这个属性的值是"TEXT",这是默认值。较新的浏览器还支持其他值,也就是说,可以接收其他格式的数据。

你可以把responseType设为blob,表示服务器传回的是二进制对象。

  var xhr = new XMLHttpRequest();

  xhr.open('GET', '/path/to/image.png');

  xhr.responseType = 'blob';

接收数据的时候,用浏览器自带的Blob对象即可。

  var blob = new Blob([xhr.response], {type: 'image/png'});

注意,是读取xhr.response,而不是xhr.responseText。

你还可以将responseType设为arraybuffer,把二进制数据装在一个数组里。

  var xhr = new XMLHttpRequest();

  xhr.open('GET', '/path/to/image.png');

  xhr.responseType = "arraybuffer";

接收数据的时候,需要遍历这个数组。

  var arrayBuffer = xhr.response;

  if (arrayBuffer) {

    var byteArray = new Uint8Array(arrayBuffer);

    for (var i = 0; i < byteArray.byteLength; i++) {

      // do something

    }
  }

更详细的讨论,请看Sending and Receiving Binary Data。

九、进度信息

新版本的XMLHttpRequest对象,传送数据的时候,有一个progress事件,用来返回进度信息。

它分成上传和下载两种情况。下载的progress事件属于XMLHttpRequest对象,上传的progress事件属于XMLHttpRequest.upload对象。

我们先定义progress事件的回调函数。

  xhr.onprogress = updateProgress;

  xhr.upload.onprogress = updateProgress;

然后,在回调函数里面,使用这个事件的一些属性。

  function updateProgress(event) {

    if (event.lengthComputable) {

      var percentComplete = event.loaded / event.total;

    }

  }

上面的代码中,event.total是需要传输的总字节,event.loaded是已经传输的字节。如果event.lengthComputable不为真,则event.total等于0。

与progress事件相关的,还有其他五个事件,可以分别指定回调函数:

  * load事件:传输成功完成。

  * abort事件:传输被用户取消。

  * error事件:传输中出现错误。

  * loadstart事件:传输开始。

  * loadEnd事件:传输结束,但是不知道成功还是失败。

十、阅读材料

  1. Introduction to XMLHttpRequest Level 2: 新功能的综合介绍。

  2. New Tricks in XMLHttpRequest 2:一些用法的介绍。

  3. Using XMLHttpRequest:一些高级用法,主要针对Firefox浏览器。

  4. HTTP Access Control:CORS综述。

  5. DOM access control using cross-origin resource sharing:CORS的9种HTTP头信息

  6. Server-Side Access Control:服务器端CORS设置。

  7. Enable CORS:服务端CORS设置。

(完)

文档信息

相关文章

  • 2018.03.20: Node 调试工具入门教程

    JavaScript 程序越来越复杂,调试工具的重要性日益凸显。客户端脚本有浏览器,Node 脚本怎么调试呢?
  • 2018.02.23: Node 定时器详解
    JavaScript 是单线程运行,异步操作特别重要。
  • 2017.09.19: 《ES6 标准入门(第3版)》上市了!
    2017年6月,TC39 委员会正式发布了《ES2017 标准》。
  • 2017.09.07: asm.js 和 Emscripten 入门教程
    Web 技术突飞猛进,但是有一个领域一直无法突破 ---- 游戏。

广告(购买广告位)

留言(31条)

qiayue 说:

学习了,html5的新特性真让人着迷

2012年9月 9日 10:21 | # | 引用

RedNax 说:

其实IE8,9也支持跨域资源共享,不过用的是 XDomainRequest 对象,而且做法和w3c标准不同,不是设置在header里而是要放一个文件在服务器上(类似Flash跨域的做法)。

2012年9月 9日 23:21 | # | 引用

ToFishes 说:

引用RedNax的发言:

其实IE8,9也支持跨域资源共享,不过用的是 XDomainRequest 对象,而且做法和w3c标准不同,不是设置在header里而是要放一个文件在服务器上(类似Flash跨域的做法)。

IE8,9也支持跨域没有错,可用接口单一,但是并不需要放一个文件在服务器上,也不类似flash。

我做过测试: http://cssor.com/cross-origin-resource-sharing.html

2012年9月10日 10:59 | # | 引用

马猴 说:

刚看了《黑客与画家》,确实是一本不可多得的好书!

2012年9月10日 20:41 | # | 引用

RedNax 说:

引用ToFishes的发言:

IE8,9也支持跨域没有错,可用接口单一,但是并不需要放一个文件在服务器上,也不类似flash。

我做过测试: http://cssor.com/cross-origin-resource-sharing.html

哦,看了一下文档确实如此。看来是我和什么混起来了……

2012年9月10日 20:51 | # | 引用

dirty 说:

Websocket比xhr更强大,可以实现实时的push,现在只能靠flash,随着支持浏览器的普及,将会看到更多用websocket的网站,阮先生也可以介绍一下

2012年9月11日 11:24 | # | 引用

土木坛子 说:

最近的内容涉及到好多技术的细节问题,没有太大的兴趣,当然了,写什么是阮兄的自由。

2012年9月12日 05:20 | # | 引用

瞬间的永恒 说:

js跨域还在研究当中,学习啦

2012年9月24日 16:37 | # | 引用

Jak Wings 说:

不错,假如可以顺便知道支持的浏览器的大致版本号就好了。

2012年10月 2日 15:54 | # | 引用

甄码农 说:

据我了解文中提到的“跨域资源共享(CORS)”目前还是w3c的草案,还没有正式发布。

2012年11月22日 17:22 | # | 引用

keshin 说:

博主,关于CORS,最好再加上Preflighted request的内容

如果要使用除GET和POST以外的方法,或者想用content-type不是application/x-www-form-urlencoded, multipart/form-data, or text/plain 的POST,需要在request的header中添加额外的custom header

Preflighted requests

Unlike simple requests (discussed above), "preflighted" requests first send an HTTP OPTIONS request header to the resource on the other domain, in order to determine whether the actual request is safe to send. Cross-site requests are preflighted like this since they may have implications to user data. In particular, a request is preflighted if:

It uses methods other than GET or POST. Also, if POST is used to send request data with a Content-Type other than application/x-www-form-urlencoded, multipart/form-data, or text/plain, e.g. if the POST request sends an XML payload to the server using application/xml or text/xml, then the request is preflighted.
It sets custom headers in the request (e.g. the request uses a header such as X-PINGOTHER)

https://developer.mozilla.org/en-US/docs/HTTP/Access_control_CORS?redirectlocale=en-US&redirectslug=HTTP_access_control#Preflighted_requests

http://arunranga.com/examples/access-control/preflightInvocation.html

2013年2月 6日 14:32 | # | 引用

Jak Wings 说:

这里有不少的Demo可以参考:http://tiffanybbrown.com/presentation/2011/xhr2/

2013年2月20日 08:55 | # | 引用

jalorchen 说:

楼主您好,请问您本人是否试过XMLHttpRequest上传文件?如果有,请指教,最好是您完整的JS代码,我无恶意,通过实践之后只是对XMLHttpRequest上传文件表示质疑。毕竟他归根结底还是一个AJAX,欢迎QQ或是邮件交流和指点,谢谢O(∩_∩)O.qq:303834036

2013年3月17日 18:37 | # | 引用

pepepe 说:

正在学习跨文档通信 谢谢楼主的资料0w0

2013年4月16日 21:08 | # | 引用

Thyiad 说:

引用jalorchen的发言:

楼主您好,请问您本人是否试过XMLHttpRequest上传文件?如果有,请指教,最好是您完整的JS代码,我无恶意,通过实践之后只是对XMLHttpRequest上传文件表示质疑。毕竟他归根结底还是一个AJAX,欢迎QQ或是邮件交流和指点,谢谢O(∩_∩)O.qq:303834036

说到底,就是http协议,当然可以上传文件。 利用formdata上传过文件,将头信息更改为application/multiple,请求信息中还需要加入boundary信息,后台就可以进行解析了。后台用第三方组件解析要方便一些,我用的就是java的commonupload组件。

2014年3月17日 14:05 | # | 引用

欧文 说:

引用dirty的发言:

Websocket比xhr更强大,可以实现实时的push,现在只能靠flash,随着支持浏览器的普及,将会看到更多用websocket的网站,阮先生也可以介绍一下

是呀,阮老师可以介绍一下web socket.

2014年4月11日 19:48 | # | 引用

jianwu5 说:

引用dirty的发言:

Websocket比xhr更强大,可以实现实时的push,现在只能靠flash,随着支持浏览器的普及,将会看到更多用websocket的网站,阮先生也可以介绍一下

Flash的错在于它只是一个插件,小三永远转不了正。我下载新版firefox后,一启动就提示Flash崩溃,用户遇到这种情况怎么跟他解析?!

2014年10月17日 23:51 | # | 引用

189 说:

chrome 38.0已经支持xhr的timeout了

2014年11月 3日 13:53 | # | 引用

jalorchen 说:

引用Thyiad的发言:

说到底,就是http协议,当然可以上传文件。
利用formdata上传过文件,将头信息更改为application/multiple,请求信息中还需要加入boundary信息,后台就可以进行解析了。后台用第三方组件解析要方便一些,我用的就是java的commonupload组件。

谢谢兄弟指点,我会按照您的指点尝试一下。

2015年3月21日 15:25 | # | 引用

请问阮老师 说:

请问发送数据时,可否发送blob数据?文章只说了接收数据可以接收blob

2015年7月25日 17:37 | # | 引用

孔明 说:

谢谢阮兄,刚好要用到这个知识点!

2015年11月 6日 11:19 | # | 引用

山姆大叔 说:

使用阮老师提供的formData对象上传的文件(异步方式),后台(java)不知道该如何解析啊,求各位大神指点,谢谢!

2016年1月14日 22:28 | # | 引用

微凉的倾城时光 说:

谢谢楼主大大!感觉收获良多!

2016年3月20日 19:02 | # | 引用

momognu 说:

使用起来和Android的AsyncTask挺像啊

2016年3月28日 12:23 | # | 引用

老K 说:

引用山姆大叔的发言:

使用阮老师提供的formData对象上传的文件(异步方式),后台(java)不知道该如何解析啊,求各位大神指点,谢谢!

java没有像php的$_FILES类吗,一样的处理方式啊,和直接form提交没啥区别吧

2016年5月 4日 17:14 | # | 引用

老K 说:

引用请问阮老师的发言:

请问发送数据时,可否发送blob数据?文章只说了接收数据可以接收blob

void send();
void send(ArrayBuffer data);
void send(Blob data);
void send(Document data);
void send(DOMString? data);
void send(FormData data);

2016年5月 4日 17:17 | # | 引用

戈雅 说:

问下,关于上传进度 【event.loaded是已经传输的字节】 event里面的数据是从本地获取的还是服务的返回的?

2016年6月12日 15:28 | # | 引用

阮老师你好 说:

onreadystatechange应该在open和send之前设定吧,否则一些状态会捕捉不到

2016年7月29日 00:30 | # | 引用

real 说:

引用阮老师你好的发言:

onreadystatechange应该在open和send之前设定吧,否则一些状态会捕捉不到

现在使用onload

2017年3月17日 12:10 | # | 引用

小小苏 说:

文件进度需要服务端支持把,能不能写几行服务端的伪代码,我们也好理解

2018年3月28日 12:50 | # | 引用

warryy 说:

引用小小苏的发言:

文件进度需要服务端支持把,能不能写几行服务端的伪代码,我们也好理解

这个应该不需要服务端支持吧

2018年3月28日 15:30 | # | 引用

转载于:https://www.cnblogs.com/yaowen/p/8759423.html

XMLHttpRequest Level 2 使用指南相关推荐

  1. The response status was 0. Check out the W3C XMLHttpRequest Level 2 spec for

    Created by Jerry Wang, last modified on Apr 21, 2015 使用postman时遇到如下错误: 解决方法: 打开该超链接,点击绿色区域内的超链接: 即可正 ...

  2. xmlhttprequest level 2

    http://caniuse.com/xhr2 转载于:https://www.cnblogs.com/fullhouse/archive/2012/04/24/2468892.html

  3. [NOTE] XMLHttpRequest

    [NOTE] XMLHttpRequest 前言 是对浏览器接口 XMLHttpRequest的学习笔记 主要是因为最近学习的些安全内容(CSRF等)都涉及到了这个 因此来简单学习下 很多Web应用认 ...

  4. [Javascript]XMLHttpRequest对象实现下载进度条

    摘要 可以通过设置一个XMLHttpRequest对象的responseType属性来改变一个从服务器上返回的响应的数据类型.可用的属性值为空字符串 (默认), "arraybuffer&q ...

  5. XMLHttpRequest和Ajax

    XMLHttpRequest和Ajax的关系 ajax是一种技术方案,但并不是一种新技术. ajax最核心的依赖是浏览器提供的XMLHttpRequest对象. 所以我用一句话来总结两者的关系:我们使 ...

  6. JavaScript怎么上传图片

    在XMLHttpRequest Level2出台之前,大多数的异步上传图片都是利用iframe去实现的. 至于具体的实现细节,我就不在这边啰嗦的,Google一下就有文章谈这个东西. 这次主要说说,怎 ...

  7. 【转】4.2使用jQuery.form插件,实现完美的表单异步提交

    传送门:异步编程系列目录-- 示例下载:使用jQuery.form插件,实现完美的表单异步提交.rar 抓住6月份的尾巴,今天的主题是 今天我想介绍的是一款jQuery的插件:Jquery.form. ...

  8. 【转】4.1触碰jQuery:AJAX异步详解

    传送门:异步编程系列目录-- 示例源码:触碰jQuery:AJAX异步详解.rar AJAX 全称 Asynchronous JavaScript and XML(异步的 JavaScript 和 X ...

  9. phpstudy mysql建表_MySQL_总结MySQL建表、查询优化的一些实用小技巧,MySQL建表阶段是非常重要的一 - phpStudy...

    总结MySQL建表.查询优化的一些实用小技巧 MySQL建表阶段是非常重要的一个环节,表结构的好坏.优劣直接影响着后续的管理维护,赶在明天上班前分享总结个人MySQL建表.MySQL查询优化积累的一些 ...

最新文章

  1. PHP TP5框架 安装运行 Warning: require(E:\phpstudy_pro\WWW\TP5\tp5\public/../thinkphp/base.php): failed to
  2. mysql删除默认密码_修改mysql默认密码方法
  3. 导出真实表格显示列数不能超过256_平均月薪真有6万5?说说我所知道的金融人真实薪酬...
  4. NoSQL数据库之Redis数据库:Redis的介绍与安装部署(redis-2.8.19/3.2.5)
  5. MySQL安装错误:/usr/local/mysql/libexec/mysqld: unknown option '--skip-federated'
  6. java 仿百度文库源码_java开发_模仿百度文库_SWFTools_源码下载
  7. js 实现轻量ps_简单轻量的池实现
  8. 传感器为什么在低量程偏差大_传感器作业
  9. ar路由器 pppoe下发ipv6 dns_手机从路由器获取IP、光猫PPPOE拨号过程、IP/VLAN
  10. jenkins修改数据存放路径
  11. 使用MyEclipse快速开发图形化界面
  12. 2.shiro+jdbc+idea+maven数据库
  13. CMD命令关闭指定PID进程
  14. 小程序-demo:小程序示例-page/api
  15. socket10053
  16. 第二章 C++编程简介【信息学奥赛】
  17. java 启动方式 java -jar xx.jar
  18. 服务器修改了 金碟软件用不到,金蝶软件金蝶软件KIS系统客户端连接服务器时,有时会有连接不上的情况,提示服务器不是有效的,请重新设置...
  19. AD7799称重系统
  20. 什么样的IDC才符合国家标准?

热门文章

  1. 使用srvany.exe将任何程序作为Windows服务运行
  2. java json lib 日期
  3. Java NIO使用及原理分析(二)
  4. 打开工程会提示下载的可能原因和可能解决方法
  5. 关于MYSQL 的 AUTO-INC Locks
  6. android okhttp使用cookie请求
  7. Android Studio下载及安装3.0版本
  8. Android PopupWindow 隐藏软键盘的方法
  9. TensorFlow数据读取机制:文件队列 tf.train.slice_input_producer和 tf.data.Dataset机制
  10. java.lang包—对象基类Object