Ajax
一、Ajax概念
什么是AJAX
AJAX 的英文全称为 Asynchronous JavaScript And XML,Asynchronous 是异步的意思。何为异步呢?在这里异步是指通过 AJAX 向服务器请求数据,在不刷新整个页面的情况下,更新页面上的部分内容。
- 网页中发生一个事件(页面加载、按钮点击)0
- 由 JavaScript 创建 XMLHttpRequest 对象
- XMLHttpRequest 对象向 web 服务器发送http请求
- 服务器处理该请求
- 服务器将响应发送回网页
- 由 JavaScript 读取响应
- 由 JavaScript 执行正确的动作(比如更新页面)
AJAX 在这个过程中相当于是服务员,用户点好菜,由服务员把菜单交给厨师,厨师做好菜,由服务员把菜送到用户的餐桌上。
同步与异步
浏览器如果直接向服务器请求数据的话,在请求过程中,你是不能对页面进行其他操作的,这叫同步请求,而把请求数据这个活外包给 AJAX 后,在请求过程中,用户还是可以对页面进行其他操作,这就是我们的异步请求了
XML
XML被用来传输和存储数据,随着时间的推移和技术的进步,JSON 由于其简洁性和易用性,逐渐成为 AJAX 和其他 web 技术中的首选数据交换格式。现在,许多现代的 AJAX 实现和框架(例如 jQuery 和 Axios)都支持 JSON 数据格式,而不是 XML。在 AJAX 最初被提出的时候(大约 2004 年),JSON(2009年被列入ES5标准) 还没有像现在这样被广泛接受和应用。XML 作为一种成熟的数据格式,已经有了很多处理和解析的工具和技术。
JSON
JSON 是一种存储和交换数据的语法
JSON 是一种轻量级的数据交换格式
在 JSON 中,键必须是字符串,由双引号包围:
{"name":"Bill Gates" }//JSON
在 JavaScript 中,键可以是字符串、数字或标识符名称:
{name:"Bill Gates" }//JavaScript
-交换数据
当数据在浏览器与服务器之间进行交换时,这些数据只能是文本。
JSON 属于文本,并且我们能够把任何 JavaScript 对象转换为 JSON,然后将 JSON 发送到服务器。
我们也能把从服务器接收到的任何 JSON 转换为 JavaScript 对象。
以这样的方式,我们能够把数据作为 JavaScript 对象来处理,无需复杂的解析和转译。
-为什么使用 JSON?
因为 JSON 格式仅仅是文本,它能够轻松地在服务器浏览器之间传输,并用作任何编程语言的数据格式。
JavaScript 提供內建函数把以 JSON 格式写的字符串转换为原生 JavaScript 对象:
JSON.parse()
因此,如果您以 JSON 格式从服务器接收数据,那么您可以像任何其他 JavaScript 对象那样使用它。
JSON 与 XML 的差异在于:
- JSON 不使用标签
- JSON 更短
- JSON 的读写速度更快
- JSON 可使用数组
最大的不同在于:
XML 必须使用 XML 解析器进行解析。而 JSON 可通过标准的 JavaScript 函数进行解析。
为什么 JSON 比 XML 更好?
- XML 比 JSON 更难解析。
- JSON 被解析为可供使用的 JavaScript 对象。
对于 AJAX 应用程序,JSON 比 XML 更快更易用:
使用 XML
- 读取 XML 文档
- 使用 XML DOM 遍历文档
- 提取变量中存储的值
使用 JSON
- 读取 JSON 字符串
- JSON.Parse JSON 字符串
二、XMLHttpRequest 对象
1. 创建 XMLHttpRequest 对象
在 AJAX 中,XMLHttpRequest 对象是用来与服务器进行数据交换的,是AJAX的基石。其创建如下所示:
var httpRequest = new XMLHttpRequest();
为了保证浏览器的兼容性,我们可以用以下方式来创建。
if (window.XMLHttpRequest) {
// Mozilla,Safari,IE7+ 等浏览器适用
httpRequest = new XMLHttpRequest();
} else if (window.ActiveXObject) {
// IE 6 或者更老的浏览器适用
httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
}
2.向服务器发送请求
在步骤一中我们已经创建了用于服务器交换数据的 XMLHttpRequest 对象,要向服务器发送请求,我们需要调用该对象中的 open 和 send 方法。
其使用如下:
// 规定发送请求的一些要求
httpRequest.open("method", "url", async);
// 将请求发送到服务器
httpRequest.send();
| 方法 | 描述 |
|---|---|
| open(method, url, async) | 规定请求的类型 |
| • method:请求的类型:GET 还是 POST | |
| • url:服务器(文件)位置 | |
| • async:true(异步)或 false(同步) | |
| send() | 向服务器发送请求(用于 GET) |
| send(string) | 向服务器发送请求(用于 POST) |
GET 还是 POST?
GET 比 POST 更简单更快,可用于大多数情况下。
- GET通常用于请求数据
- POST用于提交数据
不过,请在以下情况始终使用 POST:
- 缓存文件不是选项(更新服务器上的文件或数据库)
- 向服务器发送大量数据(POST 无大小限制)
- 发送用户输入(可包含未知字符),POST 比 GET 更强大更安全
url - 服务器上的文件
open() 方法的 url 参数,是服务器上文件的地址:
xhttp.open("GET", "ajax_test.asp", true);
该文件可以是任何类型的文件,如 .txt 和 .xml,或服务器脚本文件,如 .asp 和 .php(它们可以在发送回响应之前在服务器执行操作)。
异步 - true 还是 false?
如需异步发送请求,open() 方法的 async 参数必须设置为 true:
xhttp.open("GET", "ajax_test.asp", true);
发送异步请求对 web 开发人员来说是一个巨大的进步。服务器上执行的许多任务都非常耗时。在 AJAX 之前,此操作可能会导致应用程序挂起或停止。
通过异步发送,JavaScript 不必等待服务器响应,而是可以:
- 在等待服务器响应时执行其他脚本
- 当响应就绪时处理响应
同步请求
如需执行同步的请求,请把 open() 方法中的第三个参数设置为 false:
xhttp.open("GET", "ajax_info.txt", false);
有时 async = false 用于快速测试。你也会在更老的 JavaScript 代码中看到同步请求。
由于代码将等待服务器完成,所以不需要 onreadystatechange 函数:
我们不推荐同步的 XMLHttpRequest (async = false),因为 JavaScript 将停止执行直到服务器响应就绪。如果服务器繁忙或缓慢,应用程序将挂起或停止。
同步 XMLHttpRequest 正在从 Web 标准中移除,但是这个过程可能需要很多年。
现代开发工具被鼓励对使用同步请求做出警告,并且当这种情况发生时,可能会抛出 InvalidAccessError 异常。
3.服务器响应状态
当 httpRequest.readyState 为 4 并且 httpRequest.status 等于 200 时,说明数据请求成功,其使用如下:
httpRequest.onreadystatechange = function () {
if (httpRequest.readyState == 4 && httpRequest.status == 200) {
// 请求成功执行的代码
} else {
// 请求失败执行的代码
}
};
<!DOCTYPE html>
<html>
<style>
table,
th,
td {
border: 1px solid black;
border-collapse: collapse;
}
th,
td {
padding: 5px;
}
</style>
<body>
<h1>XMLHttpRequest 对象</h1>
<button type="button" onclick="loadDoc()">获取我的音乐列表</button>
<br /><br />
<table id="demo"></table>
<script>
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
myFunction(this);
}
};
xhttp.open("GET", "music_list.xml", true);
xhttp.send();
}
//用于处理XML数据并构建表格
function myFunction(xml) {
var i;
var xmlDoc = xml.responseXML; //从XMLHttpRequest对象获取响应的XML数据,并将其赋值给xmlDoc变量
var table =
"<tr><th>曲目</th><th>艺术家</th><th>专辑</th><th>国家</th><th>公司</th><th>年份</th></tr>"; //初始化一个字符串变量table,用于构建表格
var x = xmlDoc.getElementsByTagName("TRACK"); // 从xmlDoc中获取所有标签名为“TRACK”的元素,并将结果赋值给x变量
for (i = 0; i < x.length; i++) {
table +=
// 将当前“ARTIST”元素的第一个子节点的值(即文本内容)添加到txt字符串中,并添加一个换行符,nodeValue返回节点的值
"<tr><td>" +
x[i].getElementsByTagName("TITLE")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("ARTIST")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("ALBUM")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("COUNTRY")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("COMPANY")[0].childNodes[0].nodeValue +
"</td><td>" +
x[i].getElementsByTagName("YEAR")[0].childNodes[0].nodeValue +
"</td></tr>"; //在table字符串后追加一个新的表格行和数据
}
document.getElementById("demo").innerHTML = table; //将ID为“demo”的元素的内容设置为table字符串,从而显示表格
}
</script>
</body>
</html>
三、XMLHttpRequest 对象属性
1.onreadystatechange
我们使用 HTTP 请求数据后,请求是否成功,会反馈给我们相应的请求状态。我们使用 onreadystatechange 去检查响应的状态,onreadystatechange是一个事件处理器,它在 XMLHttpRequest 对象的 readyState 属性发生变化时调用的函数。(它是一个回调函数)
2.readyState
readyState 的值代表请求的状态,当XMLHttpRequest对象把HTTP请求发送到服务器端时,会经历若干状态,一直等待直到请求被处理,然后再接收一个响应。
它的取值有以下几种:
| 值 | 状态 | 描述 |
|---|---|---|
| 0 | UNSENT | 代理被创建,但尚未调用 open() 方法。初始化请求 |
| 1 | OPENED | open() 方法已经被调用。已与服务器建立连接 |
| 2 | HEADERS_RECEIVED | send() 方法已经被调用,并且头部和状态已经可获得。请求被接受 |
| 3 | LOADING | 下载中;responseText 属性已经包含部分数据。请求中 |
| 4 | DONE | 下载操作已完成,可以在客户端使用了 |
3.status
status 的值是一个无符号短整型 返回了 **XMLHttpRequest 响应中的数字状态码**。在请求完成前,status 的值为 0。值得注意的是,如果 XMLHttpRequest 出错,浏览器返回的 status 也为 0。status 码是标准的 HTTP status codes。举个例子,status 200 代表一个成功的请求。如果服务器响应中没有明确指定 status 码,XMLHttpRequest.status 将会默认为 200。
HTTP 响应状态码用来表明特定 HTTP 请求是否成功完成。 响应被归为以下五大类:
- 信息响应 (
100–199) - 成功响应 (
200–299) - 重定向消息 (
300–399)304 Not Modified说明无需再次传输请求的内容,也就是说可以使用缓存的内容,使用ctrl+F5强制刷新可再次200
- 客户端错误响应 (
400–499)//常见的404: 未找到页面 - 服务端错误响应 (
500–599)
var xhr = new XMLHttpRequest();
console.log("UNSENT", xhr.status);
xhr.open("GET", "/server", true);
console.log("OPENED", xhr.status);
xhr.onprogress = function () {
console.log("LOADING", xhr.status);
};
xhr.onload = function () {
console.log("DONE", xhr.status);
};
xhr.send(null);
/**
* 输出如下:
*
* UNSENT(未发送)0
* OPENED(已打开)0
* LOADING(载入中)200
* DONE(完成)200
*/
4.statusText
返回了XMLHttpRequest 请求中由服务器返回的一个[DOMString](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String) 类型的文本信息,这则信息中也包含了响应的数字状态码。这个属性包含了返回状态对应的文本信息,例如"OK"或是"Not Found"。如果请求的状态[readyState](https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest/readyState)的值为"UNSENT"或者"OPENED",则这个属性的值将会是一个空字符串。如果服务器未明确指定一个状态文本信息,则statusText的值将会被自动赋值为"OK"。
var xhr = new XMLHttpRequest();
console.log("0 UNSENT", xhr.statusText);
xhr.open("GET", "/server", true);
console.log("1 OPENED", xhr.statusText);
xhr.onprogress = function () {
console.log("3 LOADING", xhr.statusText);
};
xhr.onload = function () {
console.log("4 DONE", xhr.statusText);
};
xhr.send(null);
/**
* 输出如下:
*
* 0 UNSENT
* 1 OPENED
* 3 LOADING OK
* 4 DONE OK
*/
5.onload
使用 XMLHttpRequest 对象时,您可以定义一个回调函数,以便在请求收到答复时执行(readyState==4)。
请在 XMLHttpRequest 对象的 onload 属性中定义该函数:
6.responseText
以字符串形式返回响应数据。
document.getElementById("demo").innerHTML = xhttp.responseText;
7.responseXML
XML HttpRequest 对象有一个內建的 XML 解析器。
ResponseXML 属性以 XML DOM 对象返回服务器响应。
使用此属性,您可以把响应解析为 XML DOM 对象:
<!DOCTYPE html>
<html>
<body>
<h1>XMLHttpRequest 对象</h1>
<p id="demo"></p>
<script>
var xhttp, xmlDoc, txt, x, i;
xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
xmlDoc = this.responseXML;
txt = "";
x = xmlDoc.getElementsByTagName("ARTIST");//获取标签为ASTIST的集合
for (i = 0; i < x.length; i++) {
txt = txt + x[i].childNodes[0].nodeValue + "<br>";//nodeValue返回节点的值
}
document.getElementById("demo").innerHTML = txt;
}
};
xhttp.open("GET", "music_list.xml", true);
xhttp.send();
</script>
</body>
</html>
四、XMLHttpRequest 对象方法
getAllResponseHeaders() 方法
返回资源的所有头信息,如长度,服务器类型,内容类型,最后修改等
<!DOCTYPE html>
<html>
<body>
<h1>XMLHttpRequest 对象</h1>
<p>
getAllResponseHeaders()
函数返回资源的所有头信息,如长度,服务器类型,内容类型,最后修改等:
</p>
<p id="demo"></p>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML =
this.getAllResponseHeaders();
}
};
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();
</script>
</body>
</html>
getResponseHeader() 方法
返回资源的特定头信息,如长度,服务器类型,内容类型,最后修改等
<!DOCTYPE html>
<html>
<body>
<h1>XMLHttpRequest 对象</h1>
<p>
getResponseHeader()
函数返回资源的特定头信息,如长度,服务器类型,内容类型,最后修改等:
</p>
<p>最后修改时间:<span id="demo"></span></p>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4 && this.status == 200) {
document.getElementById("demo").innerHTML =
this.getResponseHeader("Last-Modified");
}
};
xhttp.open("GET", "ajax_info.txt", true);
xhttp.send();
</script>
</body>
</html>
五、jsonserver使用
1.安装node环境
输入node检查是否安装成功
2.安装 json-server
npm i -g json-server 安装
安装完后使用json-server 查看是否安装成功

如果安装失败,这是因为你的系统禁止使用,解决方式也很简单:
- 我们使用管理员方式打开 Power Shell。
- 输入
Get-ExecutionPolicy,可以查看到当前的策略。 - 输入
Set-ExecutionPolicy RemoteSigned,设置当前的策略为 RemoteSigned。 - 输入y后在运行就可以了。
3.使用
json-server --watch db.json
<!DOCTYPE html>
<html>
<body>
<div id="demo">
<h1>XMLHttpRequest 对象</h1>
<button type="button" onclick="loadDoc()">修改内容</button>
</div>
<script>
function loadDoc() {
var xhttp = new XMLHttpRequest();
xhttp.onload = function () {
document.getElementById("demo").innerHTML = this.responseText;
};
xhttp.open("GET", "http://localhost:3000/posts", true);
xhttp.send();
}
</script>
</body>
</html>
{
"posts": [
{
"id": 1,
"title": "json-server",
"author": "typicode"
}
],
"comments": [
{
"id": 1,
"body": "some comment",
"postId": 1
}
],
"profile": {
"name": "typicode"
}
}
六、使用JSONPlaceHolder的实例
👉 JSONPlaceHolder是一个**免费的HTTP请求假数据接口**使用此地址可以获取到文章列表假数据,共100条,有帖子ID、发贴人ID、标题、内容
jsonplaceholder.typicode.com/posts
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
span {
display: flex;
}
</style>
</head>
<body>
<div id="demo"></div>
<script>
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState == 4) {
var response = JSON.parse(this.responseText);
console.log(response);
response.forEach((element) => {
let userid = document.createElement("span");
let usertitle = document.createElement("span");
let userbody = document.createElement("span");
userid.textContent = element.id;
usertitle.textContent = element.title;
userbody.textContent = element.body;
demo.appendChild(userid);
demo.appendChild(usertitle);
demo.appendChild(userbody);
});
}
};
xhttp.open("GET", "https://jsonplaceholder.typicode.com/posts", true);
xhttp.send();
</script>
</body>
</html>