# 第十四章 *AJAX*

## 本章指引

本章将为完成对 *AJAX* 基础知识的学习,并学习使用一个功能强大的第三方库 *Mock.js*

本章主要包含以下内容:

– *AJAX*
– *Mock.js*

 

## 14-1 *AJAX*

1999 年,微软公司发布 *IE5*,第一次引入新功能:允许 *JavaScript* 脚本向服务器发起 *HTTP* 请求。但是这个功能当时并没有引起广泛的注意。直到 2004 年 *Gmail* 的发布和 2005 年 *Google Map* 的发布,才引起广泛重视。

2005 年 2 月,*AJAX* 这个词第一次正式被提出,它指的就是围绕“允许 *JavaScript* 脚本向服务器发起 *HTTP* 请求”这个功能进行开发的一整套方法。从此,*AJAX* 成为了脚本发起 *HTTP* 通信的代名词,*W3C* 也在 2006 年发布了它的国际标准。

### 14-1-1 技术背景

在 *AJAX* 技术出现之前,客户端和服务端之间传输数据都是通过 *form* 表单。在 *Web* 应用程序中,客户通过表单提交自己输入的信息,服务器端的程序接受到客户提交的表单后,根据表单的数据内容进行处理,然后把处理结果返回给用户,这样就完成了一个简单的交互。

但是这种数据传输方式有一个很大的缺陷,就是每次用户与服务器的交互都需要重新刷新整个页面。正是因为这些缺陷的存在,才促使了 AJAX 技术的出现。

###14-1-2 概述

*AJAX* 的全称是 *Asynchronous JavaScript and XML*(译为:异步的 *JavaScript* 和 *XML*)。我们分别来翻译的话就是:

– ***Asynchronous***:异步的,即在执行 *AJAX* 请求时不会阻塞后面代码的运行。
– ***JavaScript***:使用 *JavaScript* 实现浏览器与服务器之间的数据交互。
– ***XML***:一种数据结构,*AJAX* 创建之初在与服务器进行数据交换时,使用的数据结构就是 *XML*。但是现在已经慢慢被 *JSON* 数据结构所取代。

*AJAX* 的意思就是“用 *JavaScript* 执行异步网络请求”。它不是一项新技术,而是很多原有的成熟技术的结合体。从上面的简单介绍我们可以知道:

* *Ajax* 技术包括: *XHTML* 和 *CSS* 技术、*DOM* 技术、*XML* 和 *XSTL* 技术、*XMLHttpRequest* 对象及 *JavaScript* 技术等。
* 其中:*XHTML* 和 *CSS* 是基于 *Web* 标准化的呈现,,*DOM* 实现了动态的显示和交互, *XML* 和 *XSTL* 实现数据交换与处理,,*XMLHttpRequest* 对象用于异步数据查询和检索, 最后采用 *JavaScript* 绑定和处理所有数据。

传统的 *Web* 应用程序中,每次用户的请求都会导致重新刷新整个页面,而采用 *AJAX* 以后,只需要刷新局部页面即可。

> 实现**与服务器的异步通信**、**局部刷新页面**,这就是 *AJAX* 技术的核心所在。

### 14-1-3 工作原理概述

*AJAX* 包括以下几步骤:

1. 创建 *XMLHttpRequest* 对象。
2. 打开连接。
3. 发送 *HTTP* 请求。
4. 处理服务器返回的消息,实现局部刷新。

![](/Users/olin/Desktop/前端/前端JS课件/课件/3. JS 编程进阶/4. 异步编程/images/ajax01.jpg)

图14-1 *AJAX* 工作原理图

![](/Users/olin/Desktop/前端/前端JS课件/课件/3. JS 编程进阶/4. 异步编程/images/ajax02.jpg)

图14-2 *AJAX* 与传统方式的区别

### 14-1-4 工作原理步骤详解

*AJAX* 技术的核心就是 *XMLHttpRequest* 对象(简称 *XHR*)。这是由微软首先引入的一个特性,是一种支持异步请求的技术。(后来其他浏览器开发商也都提供了相同的功能实现。)

简而言之,*XMLHttpRequest* 用于与服务器交换数据。这意味着用户操作页面后,可以不必刷新页面也能够取得新的数据。

**创建 *XMLHttpRequest***

创建一个 *XMLHttpRequest* 对象,也叫实例化一个 *XMLHttpRequest* 对象。因为 *XMLHttpRequest* 本身是一个构造函数。

“`js
let xhr = new XMLHttpRequest();
“`

 

*IE5* 是第一款引入 *XMLHttpRequest* 对象的浏览器。在 *IE5* 和 *IE6* 中,*XHR* 对象是通过 *MSXML* 库中的一个 *ActiveXObject* 对象实现的。

“`js
let xhr = new ActiveXObject(‘Microsoft.XMLHTTP’);
“`

 

而 *IE7+* 及其他标准浏览器都支持原生的 *XMLHttpRequest* 对象。为了应对所有浏览器,下面是创建 *XMLHttpRequest* 对象的兼容写法。

“`js
let xhr;
if(window.XMLHttpRequest){
// IE7+, Firefox, Chrome, Opera, Safari 浏览器执行代码
xhr = new XMLHttpRequest();
} else {
// IE6, IE5 浏览器执行代码
xhr = new ActiveXObject( ‘Microsoft.XMLHTTP’ );
}
“`

**打开连接**

*XMLHttpRequest* 的实例对象提供了一个 *open* 方法用来打开客户端与服务端之间的连接。该方法规定了请求的类型、请求的路径以及是否异步处理请求。语法结构如下:

“` js
xhr.open(method, url, async);
“`

 

参数说明:

– *method* :发送请求的方式。取值有 *GET* 和 *POST* (不区分大小写,建议使用大写)。
– *url* :请求资源的位置路径。
– *async* :控制是否异步处理请求。取值有 *true* (异步)和 *false* (同步),默认为 *true* 。

**发送请求**

*XMLHttpRequest* 的实例对象提供了一个 *send* 方法用于客户端向服务端发送请求。

“`js
xhr.send();
“`

 

**请求参数**

在向服务端发送请求的同时,是可以传递数据至服务端的。而请求方式的不同,数据的传递方式也不同。

– *GET* 请求:传递的数据是跟在 *open* 方法中的 *url* 后面。

“`js
xhr.open(“GET”,”/users/isUser?username=zhangsan&pwd=123″);
“`

 

– *POST* 请求:传递的数据是放在 *send* 方法的参数中。

“`js
xhr.send(“username=zhangsan&pwd=123”);
“`

 

**处理服务器返回的消息**

在第二步打开连接中,可以选择处理请求的方式为同步或异步。由于处理请求的方式不同,在第四步处理服务器返回消息的方式也就有所不同。

* 同步处理请求

当处理请求的方式为同步时,可以直接使用 *XMLHttpRequest* 的实例对象提供了一个 *responseText* 属性用来接收服务端返回的消息。

“` js
xhr.responseText;
“`

 

但是不推荐使用同步处理请求的方式。使用这种方式会导致 *JavaScript* 代码要一直等到服务器响应就绪后才继续执行,如果服务器繁忙或缓慢,应用程序就会挂起或停止。但是对于一些小型的请求,也是可以的。

* 异步处理请求

当处理请求的方式为异步时,需要通过 *XMLHttpRequest* 的实例对象提供的 *onreadystatechange* 事件来监听并处理服务器返回的消息。

“` js
xhr.onreadystatechange = function(){
// …
}
“`

 

从“请求准备发送”到最后“请求发送成功”,中间执行了一系列的任务,分别为:

* 0:请求未初始化,即还没有调用 *send* 方法;
* 1:服务器连接已建立,即已调用 *send* 方法,正在发送请求;
* 2:请求已接收,即 *send* 方法执行完成;
* 3:请求处理中,即正在解析响应内容;
* 4:请求已完成,且响应已就绪,即响应内容解析完成,可以在客户端进行调用了;

每执行一个任务, *XMLHttpRequest* 对象的状态值 *readyState* 都会发生改变。只要 *readyState* 属性发生改变时,就会触发 *onreadystatechange* 事件。

按照任务顺序,状态值 *readyState* 依次从 0 到 4 发生改变。

只有当状态值为 4 时,才表示请求完成。请求完成后,判断请求状态,状态码 *status* 为 200 时表示请求成功。只有请求完成并且成功了,才能处理服务端返回的消息。

“` js
xhr.onreadystatechange = function(){s
if(xhr.readyState == 4 && xhr.status == 200){
let text = xhr.responseText;
console.log( text );
}
}
“`

### 14-1-5 封装自己的 *AJAX*

我们发现 *AJAX* 的操作是一种固定的模式,这让我们想到,是否能够将其操作流程封装,让我们在以后的使用过程中更加方便。

以下就是一个封装好的 *AJAX* 方法:

“` js
/**
* 封装一个自己的ajax函数有1个参数options,该参数由下面属性组成
* @param {Object} options 是一个配置对象,其包含如下属性:
* url:发送ajax的目标url,
* success:服务器成功响应时的处理回掉函数,它有一个参数就是服务器返回的数据(json格式)
* data = {}:要发送给服务器的数据,我们要求传入一个对象类型,这里默认为空对象(即没有数据),
* type = “get”:请求的类型,默认get,
* async = true:是否异步,默认异步(true)
*/
function ajax({ url, success, data = {}, type = “get”, async = true }) {
let xhr;
//1、:创建 XMLHttpRequest 对象。
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
} else {
xhr = new ActiveXObject(“Microsoft.XMLHTTP”);
}
//2、3、:打开连接。发送 HTTP 请求。(根据类型是 get 或者 post 来决定数据 data 不同的发送方式)
if ((type = type.toLowerCase()) == ‘get’) {
xhr.open(‘get’, url + ‘?’ + jsonToString(data), true);
xhr.send();
} else if (type == ‘post’) {
xhr.open(‘post’, url, true);
xhr.setRequestHeader(“Content-Type”, “application/x-www-form-urlencoded”);//一般数据都以该方式传输
xhr.send(jsonToString(data));
}
//4、:处理服务器返回的消息,实现局部刷新。
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
success(xhr.responseText);
}
else {
// error && error();
throw new Error(“不好意思,总之你错了!”);
}
};
};
//用来将数据由json对象转换成符合url查询部分格式的字符串,方便数据的传输
function jsonToString(json) {
var arr = [];
for (var i in json) {
arr.push(i + ‘=’ + json[i]);
};
return arr.join(‘&’);
}
}
“`

 

 

## 14-2 *Mock.js*

在我们的实际开发当中,后端的接口往往是较晚才会出来。于是前端的许多开发都要等到后端的接口出来了才能进行,这样对于前端开发来说显得十分被动。如果有什么东西可以制造一些假的测试数据来模拟后端接口的话,那样前端开发就要方便很多了。

而 *Mock.js*,就刚好满足了这样的需求。*Mock.js* 的特点就是:生成随机数据、拦截 AJAX 请求。

### 14-2-1 安装 *Mock.js*

* 下载 *mock.js* 文件

*[https://raw.githubusercontent.com/nuysoft/Mock/refactoring/dist/mock.js][2]* 打开网页后,直接右键下载就 *OK* 了。

* *npm* 安装 *mock* 模块

项目路径下执行 *npm install mock* 命令。

### 14-2-2 *Mock.js* 使用

**生成随机数据**

“` js
Mock.mock( templete )
“`

参数 *templete* 表示数据模版,可以是对象或者字符串。根据数据模版来生成数据。

数据模版中的每个属性由 3 部分构成:属性名 *name* 、生成规则 *rule* 、属性值 *value* :

“` js
“name|rule”: value
“`

说明:

* 属性名和生成规则之间用竖线 | 分隔。
* 生成规则是可选的。

例:

“` js
let data = Mock.mock({
// 随机生成一个包含 4 个对象的数组
‘list|4’: [{
// 对象的 id 属性名依次加 1
‘id|+1’: 1,
// 随机产生一个中文的姓名
“name”: ‘@cname()’,
// 随机生成一个地址
addr: ‘@county(true)’, s
// 随机生成一个数字 大小在 18 到 60
‘age|18-60’: 1,
// 随机生成一个日期
birth: ‘@date()’,
// 随机生成一个整数,0/1 ,根据这个来给“男” “女”
sex: ‘@integer(0, 1)’,
// 随机生成一个邮箱
email: ‘@EMAIL()’,
// 在数组中随机找一个
‘like|1’:[‘看书’,’运动’,’听音乐’],
// 1-100 中随机生成一个保留两位小数点
‘num1|1-100.2’:1,
// 随机生成一个日期
time: “@date(‘yyyy-MM-dd’)”,
// 用正则匹配 1 开头的 11 位数字的手机号
mobile: /^1[0-9]{10}$/
}]
})
console.log( data );
“`

除了使用规则来生成随机数据之外,我们还可以通过“@”符号开头的字符串间接的使用 *Mock.js* 中的 *Random* 提供的函数,这也是生成随机数据的一种方式,还有一种方式就是使用我们学习了的正则表达式。这三种方式在上面的实例代码中都有涉及到,具体请参看官方文档(https://github.com/nuysoft/Mock/wiki)。

**拦截 *AJAX* 请求**

“` js
Mock.mock( rurl, rtype, templete )
“`

*rurl* 表示需要拦截的 *URL*。当拦截到匹配 *rurl* 的 *AJAX* 请求时,将根据数据模板 *template* 生成模拟数据,并作为响应数据返回。

例:

“` js
$.ajax({
url: “/getStudent”,
type: “GET”,
success(msg){
console.log( JSON.parse(msg) );
}
})
// 字符串匹配路径
Mock.mock(“/getStudent”,”get”, {
‘list|4’: [{
// 对象的 id 属性名依次加 1
‘id|+1’: 1,
// 随机产生一个中文的姓名
“name”: ‘@cname()’
}]
})
// 正则匹配路径
Mock.mock(/\/getStudent/, {
‘list|4’: [{
// 对象的 id 属性名依次加 1
‘id|+1’: 1,
// 随机产生一个中文的姓名
“name”: ‘@cname()’
}]
})
“`

**接收 *AJAX* 请求参数**

“` js
Mock.mock( rurl, (options) => {})
“`

 

## 总结

本章主要让我们学习了 *AJAX* 和 *Mock.js* 。我们对它们应该有下面的认识:

* *AJAX* 并不是一门崭新的技术,而是前端好几种技术的结合,用来实现异步请求,局部刷新。
* 使用原生 *AJAX* 的步骤主要可以分为:创建 *XMLHttpRequest* 对象、建立连接、发送请求和接收服务器响应数据并更新页面。
* *readyState* 一共有5种状态,一般我们我们只使用状态值4来确定响应已就绪。
* 使用 *Mock.js* 可以产生随机数据,拦截 *AJAX* 请求,利用这一点我们可以使用它来模拟服务器来接收和响应客户端发出的请求。

版权声明:本文为Cyen96原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Cyen96/p/13067150.html