Ajax是一种技术,一种能够向服务器请求额外的数据而无需卸载页面的技术,能够使网页具备更优的用户体验。Ajax技术的核心是XMLHttpRequest对象(XHR)。本文从XHR开始谈起,理解Ajax技术的特点,再对跨域以及Comet等技术进行简要理解和总结。
XMLHttpRequest基本用法
XHR对象有两个常用的方法open和send。open方法用户启动一个HTTP请求,不过它不会真的发送HTTP请求。open方法接收3个参数,分别表示请求的HTTP方法、请求的URL、是否异步。XHR对象的第二个方法send用于发送open所启动的请求。send方法接收1个参数,表示HTTP请求的主体数据。如果发送的是GET请求这种没有附带主体数据的HTTP请求,则传入null即可。如果是POST请求,则传入需要POST的数据。下面是一个简单示例,向/api/data发起一个GET请求,并且是采取异步的方式发送请求,即该请求不会阻塞页面中其他js代码的执行。
var xhr = new XMLHttpRequest() xhr.open("get", "/api/data", true) xhr.send(null)
请求得到的响应数据会自动填充到XHR对象的属性上,主要有下面4个属性:
* responseText: 响应主体文本
* responseXML: 如果响应内容类型是"text/xml"或"application/xml", 这个属性中将包含响应数据的XML DOM文档
* status: 响应的HTTP状态码,一般可以将HTTP状态吗200视为成功的标识
* statusText: HTTP状态的说明
XHR对象有1个readyState属性记录了该对象从创建到收到响应数据可能会经历的5种状态,readyState的可能取值如下:
0: 还没有调用open()方法初始化请求
1: 已经调用open()方法但是还没有调用send()方法
2: 已经调用send()方法但是还没有收到响应
3: 收到部分响应数据,还有部分数据没收到
4: 收到全部响应数据,即响应结束,数据完备
当readyState从一个值变到另一个值的时候会触发readystatechange事件,当这个事件触发的时候只需要在事件处理器里面检查一下readyState的值是否为4,当其值为4的时候就可以对响应的数据做后续处理了。给readystatechange事件指定处理器必须在调用open()方法之前完成才能确保跨浏览器兼容性。下面是简单示例。
var xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if (xhr.readyState === 4) { console.log(xhr.status, xhr.responseText) } } xhr.open("get", "/api/data", true) xhr.send(null)
XHR对象提供setRequestHeader()方法可以设置请求的自定义HTTP头部信息,该方法接收两个参数,要设置的字段和该字段的值。在调用open()启动一个请求之后并且在send()发送请求之前调用setRequestHeader()才能设置成功。请求得到响应之后,可以通过getResponseHeader()方法获取响应的HTTP头部信息,该方法接收1个参数,即要获取的字段名。而通过getAllResponseHeaders()则可以获得所有头部信息组成的长字符串。下面是简单示例。
var xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if (xhr.readyState === 4) { console.log(xhr.status, xhr.responseText) console.log(xhr.getResponseHeader('SomeKey')) console.log(xhr.getAllResponseHeaders()) } } xhr.open("get", "/api/data", true) xhr.setRequestHeader("SomeKey", "SomeValue") xhr.send(null)
FormData
XMLHttpRequest 2级定义了FormData类型为序列化表单、创建与表单格式相同的数据、用于XHR传输提供便利。FormData提供append()方法可以直接添加数据,该方法接收两个参数键和值。FormData的构造函数可以不传参数,也可以直接传入1个表单元素。传入表单元素之后会利用该表单元素的数据来向FormData对象预先填入键值对。下面是简单示例。
var form = document.getElementById('myForm') var data = new FormData(form) data.append('someKey', 'someValue') var xhr = new XMLHttpRequest() xhr.onreadystatechange = function() { if (xhr.readyState === 4) { console.log(xhr.responseText) } } xhr.open('post', '/api/upload', true) xhr.send(data)
跨域资源共享
通过XHR实现Ajax通信会遇到一个限制,即跨域安全策略。跨域安全策略限制了“相同域名、相同端口、相同协议”,当XHR想要访问限制之外的资源就会引发安全错误。CORS(Cross-Origin Resource Sharing),跨域资源共享,其思想是通过使用自定义HTTP头部让浏览器与服务器进行沟通从而决定请求或者响应的成功与失败,需要浏览器和服务器同时支持才能实现正常的访问。目前大部分浏览器已经支持了CORS,所以写起代码跟普通的同域资源访问几乎一样,就只是把URL用绝对路径表示。因此,要实现跨域的关键还是在服务器,具体如何实现本文不深入讨论。下面是前端js的简单示例。