你真的会使用XMLHttpRequest吗?
看到标题时,有些同学可能会想:“我已经用xhr成功地发过很多个Ajax请求了,对它的基本操作已经算挺熟练了。” 我之前的想法和你们一样,直到最近我使用xhr时踩了不少坑儿,我才突然发现其实自己并不够了解xhr,我知道的只是最最基本的使用。
于是我决定好好地研究一番xhr的真面目,可拜读了不少博客后都不甚满意,于是我决定认真阅读一遍W3C的XMLHttpRequest标准。看完标准后我如同醍醐灌顶一般,感觉到了从未有过的清澈。这篇文章就是参考W3C的XMLHttpRequest标准和结合一些实践验证总结而来的。
我们通常将Ajax等同于XMLHttpRequest,但细究起来它们两个是属于不同维度的2个概念。
以下是我认为对Ajax较为准确的解释:(摘自what is Ajax)
AJAX stands for Asynchronous JavaScript and XML. AJAX is a new technique for creating better, faster, and more interactive web applications with the help of XML, HTML, CSS, and Java Script.
AJAX is based on the following open standards:
Browser-based presentation using HTML and Cascading Style Sheets (CSS).
Data is stored in XML format and fetched from the server.
Behind-the-scenes data fetches using XMLHttpRequest objects in the browser.
JavaScript to make everything happen.
从上面的解释中可以知道:ajax是一种技术方案,但并不是一种新技术。它依赖的是现有的CSS/HTML/Javascript,而其中最核心的依赖是浏览器提供的XMLHttpRequest对象,是这个对象使得浏览器可以发出HTTP请求与接收HTTP响应。
所以我用一句话来总结两者的关系:我们使用XMLHttpRequest对象来发送一个Ajax请求。
XMLHttpRequest的发展历程XMLHttpRequest一开始只是微软浏览器提供的一个接口,后来各大浏览器纷纷效仿也提供了这个接口,再后来W3C对它进行了标准化,提出了XMLHttpRequest标准。XMLHttpRequest标准又分为Level 1和Level 2。
XMLHttpRequest Level 1主要存在以下缺点:
受同源策略的限制,不能发送跨域请求;
不能发送二进制文件(如图片、视频、音频等),只能发送纯文本数据;
在发送和获取数据的过程中,无法实时获取进度信息,只能判断是否完成;
那么Level 2对Level 1 进行了改进,XMLHttpRequest Level 2中新增了以下功能:
可以发送跨域请求,在服务端允许的情况下;
支持发送和接收二进制数据;
新增formData对象,支持发送表单数据;
发送和获取数据时,可以获取进度信息;
可以设置请求的超时时间;
当然更详细的对比介绍,可以参考阮老师的这篇文章,文章中对新增的功能都有具体代码示例。
XMLHttpRequest兼容性关于xhr的浏览器兼容性,大家可以直接查看“Can I use”这个网站提供的结果XMLHttpRequest兼容性,下面提供一个截图。
从图中可以看到:
IE8/IE9、Opera Mini 完全不支持xhr对象
IE10/IE11部分支持,不支持 xhr.responseType为json
部分浏览器不支持设置请求超时,即无法使用xhr.timeout
部分浏览器不支持xhr.responseType为blob
细说XMLHttpRequest如何使用先来看一段使用XMLHttpRequest发送Ajax请求的简单示例代码。
function sendAjax() { //构造表单数据 var formData = new FormData(); formData.append('username', 'johndoe'); formData.append('id', 123456); //创建xhr对象 var xhr = new XMLHttpRequest(); //设置xhr请求的超时时间 xhr.timeout = 3000; //设置响应返回的数据格式 xhr.responseType = "text"; //创建一个 post 请求,采用异步 xhr.open('POST', '/server', true); //注册相关事件回调处理函数 xhr.onload = function(e) { if(this.status == 200||this.status == 304){ alert(this.responseText); } }; xhr.ontimeout = function(e) { ... }; xhr.onerror = function(e) { ... }; xhr.upload.onprogress = function(e) { ... }; //发送数据 xhr.send(formData); }
上面是一个使用xhr发送表单数据的示例,整个流程可以参考注释。
接下来我将站在使用者的角度,以问题的形式介绍xhr的基本使用。
我对每一个问题涉及到的知识点都会进行比较细致地介绍,有些知识点可能是你平时忽略关注的。