原生 XHR请求
# 原生 XHR请求
原生 XMLHttpRequest
(XHR)请求是一个 JavaScript 对象,用于在后台与服务器交换数据,并在不重新加载整个网页的情况下更新网页内容。
# 1. 使用 xhr
发起 GET 请求
步骤:
- 创建
xhr
对象 - 调用
xhr.open()
函数 - 调用
xhr.send()
函数 - 监听
xhr.onreadystatechange
事件
// 1. 创建 XHR 对象
var xhr = new XMLHttpRequest();
// 2. 调用 open 函数,指定请求方式与 URL 地址
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks');
// 3. 调用 send 函数,发起 Ajax 请求
xhr.send();
// 4. 监听 onreadystatechange 事件
xhr.onreadystatechange = function() {
// 4.1 监听 xhr 对象的请求状态 readyState 以及与服务器响应的状态 status
if (xhr.readyState === 4 && xhr.status === 200) {
// 4.2 打印服务器响应回来的数据
console.log(xhr.responseText); // 在控制台输出响应文本
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
- 创建 XHR 对象:通过
new XMLHttpRequest()
创建一个新的XMLHttpRequest
对象,用于发起 HTTP 请求。 - 调用
open
函数:使用xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
方法指定请求的 HTTP 方法('GET')和目标 URL 地址。 - 调用
send
函数:xhr.send()
方法发起请求。对于 GET 请求,send
方法没有参数。 - 监听
onreadystatechange
事件:xhr.readyState
表示请求的状态,4
代表请求已完成。xhr.status
表示 HTTP 响应状态码,200
代表请求成功。xhr.responseText
包含服务器返回的响应数据,使用console.log()
打印到控制台。
# 1.1 了解 xhr
对象的 readyState
属性
readyState
属性有五个状态,分别是:
0
(UNSENT):请求未初始化1
(OPENED):请求已打开,但未发送2
(HEADERS_RECEIVED):请求已发送,正在接收响应头3
(LOADING):正在接收响应体4
(DONE):响应接收完成
# 1.2 使用 xhr
发起带参数的 GET 请求
// 使用 xhr 对象发起带参数的 GET 请求时,在调用 xhr.open 时,将参数附加到 URL 地址中
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks?id=1');
xhr.send();
// 监听响应
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
- 说明:在 URL 地址后面附加查询参数,例如
http://www.liulongbin.top:3006/api/getbooks?id=1
。这种拼接在 URL 后的参数称为查询字符串。
# 2. 使用 xhr
发起 POST 请求
步骤:
- 创建
xhr
对象 - 调用
xhr.open()
函数 - 设置
Content-Type
属性(固定写法) - 调用
xhr.send()
函数,同时指定要发送的数据 - 监听
xhr.onreadystatechange
事件
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest();
// 2. 调用 open 函数,指定请求方式为 POST 和 URL 地址
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook');
// 3. 设置 Content-Type 属性(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
// 4. 调用 send 函数,将数据以查询字符串的形式提交给服务器
xhr.send('bookname=水浒传&author=施耐庵&publisher=天津图书出版社');
// 5. 监听 onreadystatechange 事件
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
- 创建 XHR 对象:使用
new XMLHttpRequest()
创建新的XMLHttpRequest
对象。 - 调用
open
函数:指定请求方式为 'POST' 和目标 URL 地址。 - 设置
Content-Type
属性:通过xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
设置请求头,指明请求体的类型为 URL 编码的表单数据。 - 调用
send
函数:将数据以查询字符串格式传递给服务器。例如'bookname=水浒传&author=施耐庵&publisher=天津图书出版社'
。 - 监听
onreadystatechange
事件:处理响应结果,同 GET 请求的处理方式相同。
# 3. JSON
JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,用于在计算机和网络之间存储和传输数据。JSON 的数据结构非常简单,主要用于表示对象和数组数据。
对象结构
// JSON 对象结构使用大括号 {} 包裹,数据以键值对的形式表示。
// 键(key)是一个字符串,必须用双引号包裹;值(value)可以是以下类型之一:
// - 数字(例如:123)
// - 字符串(例如:"hello")
// - 布尔值(例如:true 或 false)
// - null
// - 数组(例如:[1, 2, 3])
// - 对象(例如:{"key1": "value1", "key2": "value2"})
var jsonObject = {
"name": "Alice", // 字符串类型的值
"age": 25, // 数字类型的值
"isStudent": false, // 布尔值类型的值
"address": null, // null 值
"hobbies": ["reading", "sports"], // 数组类型的值
"education": { // 嵌套的对象类型的值
"degree": "Bachelor",
"year": 2023
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
- 对象结构:JSON 对象是用
{}
包裹的键值对集合。每个键必须是一个用双引号括起来的字符串,每个值可以是六种基本数据类型之一,包括数字、字符串、布尔值、null
、数组或对象。
# 3.1 JSON 语法注意事项
// JSON 的语法要求如下:
// ① 属性名必须使用双引号包裹
// 正确: {"name": "Alice"}
// 错误: {name: "Alice"}
// ② 字符串类型的值必须使用双引号包裹
// 正确: {"message": "Hello, world!"}
// 错误: {"message": 'Hello, world!'}
// ③ JSON 中不允许使用单引号表示字符串
// 正确: {"title": "Book"}
// 错误: {'title': 'Book'}
// ④ JSON 中不能写注释
// 正确: {"data": [1, 2, 3]}
// 错误: {"data": [1, 2, 3], // This is a comment}
// ⑤ JSON 的最外层必须是对象或数组格式
// 正确: {"name": "Alice"}
// 正确: [1, 2, 3]
// 错误: "name": "Alice" // 最外层不是对象或数组
// ⑥ 不能使用 undefined 或函数作为 JSON 的值
// 正确: {"value": null}
// 错误: {"value": undefined}
// 错误: {"func": function() { return "Hello"; }} // 函数不是有效的 JSON 值
// JSON 的作用:用于在计算机和网络之间存储和传输数据。
// JSON 的本质:用字符串来表示 JavaScript 对象或数组数据。
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
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
- 属性名:必须使用双引号(")括起来。
- 字符串值:也必须使用双引号。
- 单引号:JSON 不允许使用单引号来表示字符串。
- 注释:JSON 不允许包含注释;所有注释必须在外部文档中记录。
- 最外层格式:JSON 数据必须以对象(
{}
)或数组([]
)格式存在。 - 无效值:
undefined
和函数不能作为 JSON 的值。
# 3.2 序列化和反序列化
// 序列化:将 JavaScript 对象转换为 JSON 字符串
var jsObject = {
name: "Alice",
age: 25,
isStudent: false
};
// 使用 JSON.stringify() 方法将对象转换为 JSON 字符串
var jsonString = JSON.stringify(jsObject);
console.log(jsonString);
// 输出: {"name":"Alice","age":25,"isStudent":false}
// 反序列化:将 JSON 字符串转换为 JavaScript 对象
var jsonString = '{"name":"Alice","age":25,"isStudent":false}';
// 使用 JSON.parse() 方法将 JSON 字符串转换为对象
var jsObject = JSON.parse(jsonString);
console.log(jsObject);
// 输出: { name: 'Alice', age: 25, isStudent: false }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
- 序列化:使用
JSON.stringify()
方法将 JavaScript 对象转换为 JSON 字符串。这在存储或传输数据时非常有用。 - 反序列化:使用
JSON.parse()
方法将 JSON 字符串转换回 JavaScript 对象。这在接收数据并将其用于应用程序时非常有用。
# 4. 封装自己的 AJAX 函数
自定义 AJAX 函数 aini
允许用户以更简单的方式发起 AJAX 请求。函数接受一个配置对象作为参数,用户可以通过配置对象设置请求类型、URL、数据和成功回调函数。
# 4.1 定义和处理 options
参数
options
参数是传递给 aini
函数的配置对象,包括以下属性:
method
:请求的类型(例如 GET 或 POST)。url
:请求的 URL 地址。data
:请求携带的数据。success
:请求成功之后的回调函数。
# 4.2 处理 data
参数
resolveData
函数将 data
对象转化为查询字符串格式,便于在请求中提交给服务器。
/**
* 处理 data 参数,将对象转换为查询字符串
* @param {Object} data 需要发送到服务器的数据
* @returns {string} 返回拼接好的查询字符串,例如 "name=zs&age=10"
*/
function resolveData(data) {
var arr = []; // 用于存储键值对字符串
for (var k in data) {
if (data.hasOwnProperty(k)) { // 确保属性属于对象本身
arr.push(encodeURIComponent(k) + '=' + encodeURIComponent(data[k]));
}
}
return arr.join('&'); // 生成查询字符串
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
- encodeURIComponent:使用
encodeURIComponent
对键和值进行编码,以确保特殊字符(如空格、& 等)在查询字符串中被正确处理。
# 4.3 定义 aini
函数
aini
函数封装了创建和配置 XMLHttpRequest
对象的过程,并处理请求的发送与响应。
/**
* 自定义 AJAX 函数
* @param {Object} options 配置对象
* @param {string} options.method 请求的类型('GET' 或 'POST')
* @param {string} options.url 请求的 URL 地址
* @param {Object} options.data 请求携带的数据(仅在 POST 请求中使用)
* @param {Function} options.success 请求成功后的回调函数
*/
function aini(options) {
var xhr = new XMLHttpRequest(); // 创建 XMLHttpRequest 对象
// 将 data 对象转化为查询字符串
var qs = resolveData(options.data || {}); // 如果 data 为 undefined,则传递空对象
// 判断请求的类型并发起请求
if (options.method.toUpperCase() === 'GET') {
// 发起 GET 请求
xhr.open(options.method, options.url + '?' + qs, true); // true 表示异步请求
xhr.send(); // 发送请求
} else if (options.method.toUpperCase() === 'POST') {
// 发起 POST 请求
xhr.open(options.method, options.url, true); // true 表示异步请求
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded'); // 设置请求头
xhr.send(qs); // 发送数据
}
// 监听请求状态改变的事件
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status === 200) { // 请求成功
try {
var result = JSON.parse(xhr.responseText); // 解析响应的 JSON 数据
options.success(result); // 调用成功回调函数
} catch (e) {
console.error('解析 JSON 失败:', e); // 捕捉并处理 JSON 解析错误
}
} else {
console.error('请求失败,状态码:', xhr.status); // 请求失败时输出状态码
}
}
};
}
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
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
- 异步请求:
xhr.open()
的第三个参数true
指定请求为异步,推荐在大多数情况下使用异步请求。 Content-Type
:对于 POST 请求,设置请求头Content-Type
为application/x-www-form-urlencoded
。- 错误处理:添加了
try-catch
块以捕获 JSON 解析错误,并输出错误信息以帮助调试。 - 状态码处理:添加了对非200状态码的处理,帮助诊断请求失败的原因。
# 5. XMLHttpRequest Level2的新特性
# 5.1 设置 HTTP 请求时限
在使用 AJAX 请求时,有时请求可能会因为网络问题或者服务器响应延迟而变得非常缓慢。为了避免用户长时间等待,可以设置请求的超时时间。
// 创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
// 设置请求的时限为 3000 毫秒(即 3 秒)
xhr.timeout = 3000;
// 监听请求超时事件
xhr.ontimeout = function(event) {
alert('请求超时!'); // 超过设定时间后执行的回调函数
};
// 设置请求的 URL 和请求方式
xhr.open('GET', 'http://www.example.com/api/data', true); // true 表示异步请求
// 发送请求
xhr.send();
// 可以监听其他状态变化事件以获取请求状态
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status === 200) {
console.log(xhr.responseText); // 成功时处理响应数据
} else {
console.error('请求失败,状态码:', xhr.status); // 处理请求失败
}
}
};
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
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
xhr.timeout
:设置请求的超时时间。单位是毫秒(ms)。xhr.ontimeout
:当请求超时后触发的事件处理函数。xhr.open()
:用于指定请求的类型(GET/POST)和 URL 地址,并可以设置是否异步请求。xhr.send()
:发送请求到服务器。
# 5.2 FormData
对象管理表单数据
FormData
对象提供了一种处理表单数据的便捷方法,它可以用来构建表单数据集,模拟用户提交表单的行为。
# 5.2-1 使用 FormData
直接提交数据
// 1. 创建 FormData 对象
var fd = new FormData();
// 2. 为 FormData 对象添加表单项
fd.append('uname', 'zs'); // 添加用户名
fd.append('upwd', '123456'); // 添加密码
// 3. 创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
// 4. 设置请求的 URL 和请求方式
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata', true); // true 表示异步请求
// 5. 直接提交 FormData 对象
xhr.send(fd);
// 监听请求状态改变事件
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status === 200) {
console.log(xhr.responseText); // 成功时处理响应数据
} else {
console.error('请求失败,状态码:', xhr.status); // 处理请求失败
}
}
};
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
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
FormData
对象:用于创建一个可以发送表单数据的对象。fd.append()
:向FormData
对象中添加表单字段和对应的值。xhr.send(fd)
:直接将FormData
对象作为请求体发送。
# 5.2-2 使用 FormData
从现有表单获取数据
// 获取表单元素
var form = document.querySelector('#form1');
// 监听表单的 submit 事件
form.addEventListener('submit', function(e) {
e.preventDefault(); // 阻止表单的默认提交行为
// 根据表单创建 FormData 对象,会自动填充表单数据
var fd = new FormData(form);
// 创建 XMLHttpRequest 对象
var xhr = new XMLHttpRequest();
// 设置请求的 URL 和请求方式
xhr.open('POST', 'http://www.liulongbin.top:3006/api/formdata', true); // true 表示异步请求
// 发送 FormData 对象
xhr.send(fd);
// 监听请求状态改变事件
xhr.onreadystatechange = function() {
if (xhr.readyState === 4) { // 请求完成
if (xhr.status === 200) {
console.log(xhr.responseText); // 成功时处理响应数据
} else {
console.error('请求失败,状态码:', xhr.status); // 处理请求失败
}
}
};
});
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
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
FormData(form)
:创建一个FormData
对象,并从表单中自动填充数据。e.preventDefault()
:阻止表单的默认提交行为,使得 AJAX 提交得以替代传统的表单提交。
编辑此页 (opens new window)
上次更新: 2024/12/28, 18:32:08