浏览器在XMLHttpRequest类上定义了他们的HTTP API。 这个类的每一个实例都是一个独立的请求/响应对,这个对象的属性和方法允许指定请求细节和提取响应数据。
一、实例化XMLHttpResquest()
使用这个HTTP API的第一步就是实例化一个XMLHttpRequest对象:
var requestObj new XMLHttpRequest();
当然,实际开发中,不会这么简单,我们还要考虑兼容早版本的IE的问题,在IE5和IE6中它只是一个ActiveX对象。IE7之前的版本不支持非标准化的XMLHttpRequest()构造函数。我们需要这样写:
if (window.XMLHttpRequest) {
requestObj = new XMLHttpRequest();
} else {
requestObj = new ActiveXObject("Microsoft.XMLHTTP")//兼容早版本的ie, 如IE5 IE6
}
除了实例化一个XMLHttpRequest对象,我们也可以重用已有的对象,但要注意,这样会终止之前通过该对象挂起的任何请求。
请求和响应的组成
一个http请求由4部分组成:
- 方法或“动作”
- 请求的 url
- 可选的请求头集合,可能包含身份验证信息
- 可选的请求主体
HTTP响应包含3部分:
- 状态码,显示请求的状态,如是否成功
- 响应头集合
- 响应主体
二、指定请求
发起HTTP请求的下一步是调用XMLHttpRequest对象的open()方法:
request.open("方法", "URL")
open()
方法需要指定两个必要部分:方法 和 url。第一个参数为“方法”,不区分大小写,但通常使用大写,常用的方法有 “GET” “POST”
。GET 方法用于常规请求,它适用于当URL完全指定请求资源,请求对服务器没有任何副作用以及服务器响应是可缓存的。POST方法常用于HTML表单,它在请求主体中包含额外数据,且这些数据常需要存储到服务器的数据库上(副作用)。不同的额外数据服务器可能返回不同的数据。
除了POST和GET方法,还有“DELETE” “HEAD” “OPTION” “PUT”
等方法。他们都可以作为open()方法的第一个参数。
open()方法还有第三个参数,用来指定方法是同步还是异步的。而默认是异步的,这个在文章后面会细讲。
三、设置请求头
如果有请求头的话,我们可以通过
requestObj.setRequestHeader("Content-Type", " ")
来设置请求头。
要注意的是:对相同的头调用setRequestHeader()多次,新值不会取代旧值,相反,HTTP请求将包含这个头的多个副本或这个头将指定多个值。并不是所有的头都可以设置,如“Content-length””Date” “Referer” 和 “User-Agent”等,XMLHttpRequest将自动添加这些头而防止伪造它们。
四、发送请求
使用XMLHttpRequest的最后一步是指定可选的请求主体并向服务器发送它。使用send()方法:
requestObj.send(null)
GET方法没有主体,我们在send()方法中传入null或省略这个参数。POST请求通常拥有主体,同时应该配合setRequestHeader()指定的“Content-Type”头。
到现在,我们可以看到一个完整的发送请求的过程:
var requestObj;
if (window.XMLHttpRequest) {
requestObj = new XMLHttpRequest();
} else {
requestObj = new ActiveXObject("Microsoft.XMLHTTP")
}
requestObj.open("方法", url, async);
requestObj.setRequestHeader("Content-Type", "xxxxxxxx") //根据方法设置相应的头
requestObj.send();
前面部分讲了如何 发送ajax请求_,下面部分是如何 _取得响应
五、取得响应
一个完整的HTTP响应由状态码、响应头集合和响应主体组成。这些都可以通过XMLHttpRequest对象的属性和方法使用。
- status和statusText属性以数字和文本的形式返回HTTP状态码。
- getResponseHeader()和getAllResponseHeaders()能查询响应头。
- 响应主体可以从 reponseText 属性中得到文本形式,从responseXML中得到Document形式。
在send()方法发送后,我们需要知道我们的请求什么时候得到了响应,请求是否成功等,这时候我们就要用到XMLHttpResquest对象上的 readyState
属性,readyState属性
是一个整数,它指定了请求的状态:
常量 | 值 | 含义 |
---|---|---|
UNSENT | 0 | open()尚未使用 |
OPENED | 1 | open()已调用 |
HEADERS_RECEIVED | 2 | 接收到头部信息 |
LOADING | 3 | 接收到响应主体 |
DONE | 4 | 响应完成 |
通过readyState我们就可以知道当前的请求出于什么状态了,那我们怎么去监听readyState呢?其实在每次readyState改变的时候,都会触发readystatechange事件,而我们可以通过onreadystatechange属性去监听readystatechange事件。所以通过onreadystatechange属性就可以间接的监听到readyState的改变了。当然我们也可以使用addEventListener()方法来监听,但我们通常不这么做。
所以我们可以通过下面代码来获取响应信息:
requestObj.onreadystatechange = function() { // 监听readyState的变化
if (requestObj.readyState == 4) { // 判断响应是否完成
if (requestObj.status == 200) { // 判断请求是否成功
console.log(resquestObj.responseText);
}
}
}
所以到这里,我们应该知道了一个完整的原生ajax请求是怎么样的了。
// 实例化XMLHttpRequest
var requestObj;
if (window.XMLHttpResquest) {
requestObj = new XMLHttpRequest();
} else {
requestObj = new ActiveXObject("Microsoft.XMLHTTP")
}
// 发送请求
requestObj.open("TYPE", "URL");
requestObj.setRequestHeader("Content-Type", .....);
requestObj.send();
// 获取响应
requestObj.onreadystatechange = function() {
if (requestObj.readyState == 4) {
if (requestObj.status == 200) {
console.log(requestObj.reponseText);
}
}
}
六、同步请求
是否还记得前面说到,open()方法还有第三个参数,它指定请求是同步的还是异步的,而默认值为true, 使得请求为异步请求。我们可以给它传入false来实现同步请求。
requestObj.open(type, url, false);
这样我们就不需要去监听readyState的值来获知请求何时得到了响应了。
requestObj.open("TYPE", "URL", false);
requestObj.setRequestHeader("Content-Type", .....);
requestObj.send();
// 当请求得到响应才执行
if (requestObj.status != 200) throw new Error(request.statusText);
console.log(requestObj.reponseText);
同步请求是吸引人的,但是同步请求意味着什么呢?意味着由于JavaScript是单线程的,当send()方法调用后,请求发出,send()方法将阻塞这份代码,send()方法后面的代码都不会被执行,直到请求得到响应,如果连接的服务器响应慢,用户的浏览器UI就会被冻结。所以不是特殊情况,最好不用同步请求。