目录

  1. AJAX简介
    1. 优点
    2. 缺点
    3. 使用场景
  2. AJAX的核心 XMLHttpRequest对象
    1. 方法
    2. 属性
      1. XMLHttpRequest 方法
        1. abort()
        2. getAllResponseHeaders()
        3. getResponseHeader()
        4. open()
        5. sned()
        6. setRequestHeader()
  3. 发送AJAX请求
    1. 设置请求头部信息
    2. 发送AJAX请求
    3. 处理响应
  4. 其他库框架中的AJAX
    1. jQuery中的AJAX
    2. Vue.js中的AJAX
  5. 状态值和状态码
    1. 状态值于状态码:
    2. ajax状态码:
    3. ajax类库

AJAX简介

  AJAX全称为“Asynchronous Javascript And XML”, 即“异步JavaScript和XML”的意思。通过AJAX我们可以向服务器发送请求,在不阻塞页面的情况下进行数据交互,也可以理解为异步数据传输。在AJAX的帮助下我们的网页只需局部刷新即可更新数据的显示,减少了不必要的数据量,大大提高了用户体验,缩短了用户等待的时间,使得web应用程序更小、更快,更友好。

优点

  页面无刷新,用户体验好。
  异步通信,更加快的响应能力。
  减少冗余请求,减轻了服务器负担
  基于标准化的并被广泛支持的技术,不需要下载插件或者小程序

缺点

  ajax干掉了back按钮,即对浏览器后退机制的破坏。
  存在一定的安全问题。
  对搜索引擎的支持比较弱。
  破坏了程序的异常机制。
  无法用URL直接访问

使用场景

  场景 1. 数据验证
  场景 2. 按需取数据
  场景 3. 自动更新页面

AJAX的核心 XMLHttpRequest对象

创建XML对象的实例:const xhr = new XMLHttpRequest()

方法

1
2
3
4
5
6
7
8
9
10
11
12
# 准备启动一个AJAX请求
.open()
# 设置请求头部信息
.setRequestHeader()
# 发送AJAX请求
.send()
# 获得响应头部信息
.getResponseHeader()
# 获得一个包含所有头部信息的长字符串
.getAllResponseHeader()
# 取消异步请求
.abort()

属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 一个JavaScript函数对象,当readyState属性改变时会调用它。
# 回调函数会在user interface线程中调用。
onreadystatechange

# 表示“请求”/“响应”过程的当前活动阶段
# HTTP 请求的状态.当一个 XMLHttpRequest 初次创建时,
# 这个属性的值从 0 开始,直到接收到完整的 HTTP 响应,这个值增加到 4。
# 0 Uninitialized 初始化状态。XMLHttpRequest 对象已创建或已被 abort() 方法重置。
# 1 Open open() 方法已调用,但是 send() 方法未调用。请求还没有被发送。
# 2 Sent Send() 方法已调用,HTTP 请求已发送到 Web 服务器。未接收到响应。
# 3 Receiving 所有响应头部都已经接收到。响应体开始接收但未完成。
# 4 Loaded HTTP 响应已经完全接收。
# readyState 的值不会递减,除非当一个请求在处理过程中的时候调用了
# abort() 或 open() 方法。每次这个属性的值增加的时候,都会触发
# onreadystatechange 事件句柄。
.readyState

# 目前为止为服务器接收到的响应体(不包括头部),或者如果还没有接收到数据的话,
# 就是空字符串。
# 如果 readyState 小于 3,这个属性就是一个空字符串。当 readyState 为 3,
# 这个属性返回目前已经接收的响应部分。如果 readyState 为 4,这个属性保存
# 了完整的响应体。
.responseText

# 如果响应的内容类型时text/xml或application/xml,
# 该属性将保存包含着相应数据的XML DOM文档
.responseXML

# 响应的HTTP状态
.status

# HTTP状态的说明
.statusText
XMLHttpRequest 方法
abort()

取消当前响应,关闭连接并且结束任何未决的网络活动。
  这个方法把 XMLHttpRequest 对象重置为 readyState为 0 的状态,并且取消所有未决的网络活动。例如,如果请求用了太长时间,而且响应不再必要的时候,可以调用这个方法。

getAllResponseHeaders()

把 HTTP 响应头部作为未解析的字符串返回。
  如果 readyState 小于 3,这个方法返回 null。否则,它返回服务器发送的所有 HTTP 响应的头部。头部作为单个的字符串返回,一行一个头部。每行用换行符 "\r\n" 隔开。

getResponseHeader()

  返回指定的 HTTP 响应头部的值。其参数是要返回的 HTTP 响应头部的名称。可以使用任何大小写来制定这个头部名字,和响应头部的比较是不区分大小写的。
  该方法的返回值是指定的 HTTP 响应头部的值,如果没有接收到这个头部或者 readyState 小于 3 则为空字符串。如果接收到多个有指定名称的头部,这个头部的值被连接起来并返回,使用逗号和空格分隔开各个头部的值。

open()

初始化一个请求. 该方法用于JavaScript代码中;如果是本地代码, 使用 openRequest())方法代替.

注意: 在一个已经激活的request下(已经调用open()或者openRequest()方法的request)再次调用这个方法相当于调用了abort()方法。

参数:
method
  请求所使用的HTTP方法; 例如 “GET”, “POST”, “PUT”, “DELETE”等. 如果下个参数是非HTTP(S)的URL,则忽略该参数.
url
  该请求所要访问的URL
async
  一个可选的布尔值参数,默认为true,意味着是否执行异步操作,如果值为false,则send()方法不会返回任何东西,直到接受到了服务器的返回数据。如果为值为true,一个对开发者透明的通知会发送到相关的事件监听者。这个值必须是true,如果multipart 属性是true,否则将会出现一个意外。
user
  用户名,可选参数,为授权使用;默认参数为空string.
password
  密码,可选参数,为授权使用;默认参数为空string.

sned()

发送 HTTP 请求,使用传递给 open() 方法的参数,以及传递给该方法的可选请求体。

setRequestHeader()

向一个打开但未发送的请求设置或添加一个 HTTP 请求(设置请求头)。
参数:
header
  将要被赋值的请求头名称
value
  给指定的请求头赋的值

发送AJAX请求

设置请求头部信息

  每个HTTP请求和响应都会带有相应的头部信息,包含一些与数据,收发者网络环境与状态等相关信息。XMLHttpRequest对象提供的.setRequestHeader()方法为开发者提供了一个操作这两种头部信息的方法,并允许开发者自定义请求头的头部信息。
默认情况下,当发送AJAX请求时,会附带以下头部信息:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 浏览器能够处理的内容类型
Accept
# 浏览器能够显示的字符集
Accept-Charset
# 浏览器能够处理的压缩编码
Accept-Encoding
# 浏览器当前设置的语言
Accept-Language
# 浏览器与服务器之间连接的类型
Connection
# 当前页面设置的任何Cookie
Cookie
# 发出请求的页面所在的域
Host
# 发出请求的页面URI
Referer
# 浏览器的用户代理字符串
User-Agent

注意:
  部分浏览器不允许使用.setRequestHeader()方法重写默认请求头信息,因此自定义请求头信息是更加安全的方法:
# 自定义请求头
xhr.setRequestHeader("myHeader", "MyValue")

发送AJAX请求

1
2
3
4
5
6
7
8
9
10
11
12
# 发送AJAX请求
# 使用get方法发送同步请求(false)
let xhr = new XMLHttpRequest()
xhr.open('get', 'example.php', false)
xhr.setRequestHeader('myHeader', 'goodHeader')
xhr.send(null)

# POST请求
let xhr = new XMLHttpRequest()
xhr.open('post', 'example.php', false)
xhr.setRequestHeader('myHeader', 'goodHeader')
shr.send(some_data)

处理响应

同步的GET请求响应:

1
2
3
4
5
6
7
8
9
10
11
const xhr = new XMLHttpRequest()
xhr.open("get", "example.php", false)
xhr.setRequestHeader("myHeader", "goodHeader")
xhr.send(null)
# 由于是同步的AJAX请求,因此只有当服务器响应后才会继续执行下面的代码
# 因此xhr.status的值一定不为默认值
if((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log("xhr.responseText:", xhr.responseText);
} else {
console.log("Request was unsuccessful:", xhr.status);
}

  上面的代码不难理解,我们通过之前提到的xhr.status属性(如果你忘记了,它存储着响应的HTTP状态)判断请求是否成功,如果成功的话,我们将读取xhr.responseText属性中存储的返回值。但是,当我们的请求为异步时,问题就稍微变得复杂了,由于是异步的请求,在xhr.send(null)语句被执行后,JavaScript引擎会紧接着执行下面的判断语句,而这时由于尚未来得及响应,我们注定会得到一个默认的xhr.status值,因此,我们永远都不可能获取请求的资源了。
如何解决这个问题?答案是通过为XMLHTTPRequest实例添加onreadystatechange事件处理程序(当然你也可以直接使用DOM2级规范规定的.addEventListener()方法,但是注意,IE8是不支持该方法的)。
  xhr实例的readystatechange事件会监听xhr.readyState属性的变化,你可以将这个属性想象为一个计数器,随着AJAX流程的推进而不断累加,其可取的值如下:

1
2
3
4
5
  0:未初始化 -- 尚未调用.open()方法
  1:启动 -- 已经调用.open()方法,但尚未调用.send()方法
  2:发送 -- 已经调用.send()方法,但尚未接收到响应
  3:接收 -- 已经接收到部分响应数据
  4:完成 -- 已经接收到全部响应数据,而且已经可以在客户端使用了

有了这个时间处理程序对AJAX进程做监听,剩下的事就简单多了,一个异步GET请求代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const xhr = new XMLHttpRequest()
# 等价于 xhr.onreadystatechange = function(){}
# 利用onreadystatechange监测状态
xhr.onreadystatechange = () => {
# readyState为4表示请求响应完成
if(xhr.readyState == 4) {
if ((xhr.status >= 200 && xhr.status < 300) || xhr.status === 304) {
console.log("xhr.responseText:", xhr.responseText);
} else {
console.log("Request was unsuccessful:", xhr.status);
}
}
}

xhr.open('GET', 'example.php', true)
xhr.send(null)

其他库框架中的AJAX

jQuery中的AJAX

1
2
3
4
5
6
7
8
9
10
11
$.ajax({
method: 'GET', # 1.9.0本版前用'type'
url: "/test/",
dataType: 'json'
})
.done(function() {
console.log('执行成功');
})
.fail(function() {
console.log('执行出错');
})

Vue.js中的AJAX

1
2
3
4
5
Vue.http.get('/test/').then((response) => {
console.log('执行成功');
}, (response) => {
console.log('执行出错');
});

状态值和状态码

状态值于状态码:

在ajax时间运行过程中,对于访问XMLHttpRequest不是一次就完成的,而是经历多种状态后获取的结果。
对于这种状态在ajax中分为5中状态:
0: (未初始化)还没有调用send()方法。
1: (载入)已经调用send()方法,正在派发请求。
2: (载入完成)send()已经执行完成,已经接收到全部的响应内容。
3: (交互)正在解析响应内容。
4: (完成)响应内容已经解析完成,用户可以调用。

ajax状态值和状态码的区别:
ajax的状态值指,运行ajax时运行的几种状态,无论是成功还是失败都要响应的步骤。如:正在派发,正在响应等,由ajax对象和
服务器之间交互是所得。使用ajax.readyState获得(0~4)
ajax状态码是值,ajax无论请求是否成功,根据http所提及的用户信息,用服务器返回http头信息代码,使用ajax.state来获得

这就是我们在使用AJAX时为什么采用下面的方式判断所获得的信息是否正确的原因。
if(ajax.readyState == 4 && ajax.status == 200) {
putData(ajax.responseText);
}

ajax状态码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
AJAX状态码说明

1**:请求收到,继续处理
2**:操作成功收到,分析、接受
3**:完成此请求必须进一步处理
4**:请求包含一个错误语法或不能完成
5**:服务器执行一个完全有效请求失败
100——客户必须继续发出请求
101——客户要求服务器根据请求转换HTTP协议版本
200——交易成功
201——提示知道新文件的URL
202——接受和处理、但处理未完成
203——返回信息不确定或不完整
204——请求收到,但返回信息为空
205——服务器完成了请求,用户代理必须复位当前已经浏览过的文件
206——服务器已经完成了部分用户的GET请求
300——请求的资源可在多处得到
301——删除请求数据
302——在其他地址发现了请求数据
303——建议客户访问其他URL或访问方式
304——客户端已经执行了GET,但文件未变化
305——请求的资源必须从服务器指定的地址得到
306——前一版本HTTP中使用的代码,现行版本中不再使用
307——申明请求的资源临时性删除
400——错误请求,如语法错误
401——请求授权失败
402——保留有效ChargeTo头响应
403——请求不允许
404——没有发现文件、查询或URl
405——用户在Request-Line字段定义的方法不允许
406——根据用户发送的Accept拖,请求资源不可访问
407——类似401,用户必须首先在代理服务器上得到授权
408——客户端没有在用户指定的饿时间内完成请求
409——对当前资源状态,请求不能完成
410——服务器上不再有此资源且无进一步的参考地址
411——服务器拒绝用户定义的Content-Length属性请求
412——一个或多个请求头字段在当前请求中错误
413——请求的资源大于服务器允许的大小
414——请求的资源URL长于服务器允许的长度
415——请求资源不支持请求项目格式
416——请求中包含Range请求头字段,在当前请求资源范围内没有range指示值,请求也不包含If-Range请求头字段
417——服务器不满足请求Expect头字段指定的期望值,如果是代理服务器,可能是下一级服务器不能满足请求
500——服务器产生内部错误
501——服务器不支持请求的函数
502——服务器暂时不可用,有时是为了防止发生系统过载
503——服务器过载或暂停维修
504——关口过载,服务器使用另一个关口或服务来响应用户,等待时间设定值较长
505——服务器不支持或拒绝支请求头中指定的HTTP版本

ajax类库

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<script type="text/javascript">
function ajax(value){
var url = value.url;
var type = value.type || "get";
var data = value.data || "";
var success = value.success;
var error = value.error || false;

//1、创建AJAX对象
var oAjax;

try{
//Firefox,Opera 8.0+, Safari
oAjax = new XMLHttpRequest();
}catch(e){
//Internet Explorer
try{
oAjax = new ActiveXObject("Msxml2.XMLHTTP");
}catch(e){
try{
oAjax = new ActiveXObject("Microsoft.XMLHTTP");
}catch(e){
alert("浏览器不支持ajax");
return false;
}
}
}
//链接服务器
oAjax.open(type, url, true);
//发送请求
oAjax.setRequestHeader("Content-Type","application/x-www-form-urlencoded;charset=UTF-8");
oAjax.send(data);
//数据接收
oAjax.onreadystatechange = function(){
if(oAjax.readyState == 4){
if(oAjax.stack == 200){
var data = oAjax.responseText;
success(data);
}else{
if(error){
error();
}
}
}
}
}
</script>

转载:
  使用AJAX