MDN文档
https://developer.mozilla.org/zh-CN/docs/Web/API/XMLHttpRequest
理解
- 使用 XMLHttpRequest (XHR)对象可以与服务器交互, 也就是发送 ajax 请求
- 前端可以获取到数据,而无需让整个的页面刷新。
- 这使得 Web 页面可以只更新页面的局部,而不影响用户的操作。
区别一般 http 请求与 ajax 请求
- ajax 请求是一种特别的 http 请求
- 对服务器端来说, 没有任何区别, 区别在浏览器端
- 浏览器端发请求: 只有 XHR 或 fetch 发出的才是 ajax 请求, 其它所有的都是
非 ajax 请求 - 浏览器端接收到响应
(1) 一般请求: 浏览器一般会直接显示响应体数据, 也就是我们常说的刷新/
跳转页面
(2) ajax 请求: 浏览器不会对界面进行任何更新操作, 只是调用监视的回调
函数并传入响应相关数据
API
- XMLHttpRequest(): 创建 XHR 对象的构造函数
- status: 响应状态码值, 比如 200, 404
- statusText: 响应状态文本
- readyState: 标识请求状态的只读属性
0: 初始
1: open()之后
2: send()之后
3: 请求中
4: 请求完成 - onreadystatechange: 绑定 readyState 改变的监听
- responseType: 指定响应数据类型, 如果是’json’, 得到响应后自动解析响应
体数据 - response: 响应体数据, 类型取决于 responseType 的指定
- timeout: 指定请求超时时间, 默认为 0 代表没有限制
- ontimeout: 绑定超时的监听
- onerror: 绑定请求网络错误的监听
- open(): 初始化一个请求, 参数为: (method, url[, async])
- send(data): 发送请求
- abort(): 中断请求
- getResponseHeader(name): 获取指定名称的响应头值
- getAllResponseHeaders(): 获取所有响应头组成的字符串
- setRequestHeader(name, value): 设置请求头
XHR 的 ajax 封装
- 函数的返回值为 promise, 成功的结果为 response, 异常的结果为 error
- 能处理多种类型的请求: GET/POST/PUT/DELETE
- 函数的参数为一个配置对象
{
url: ‘’, // 请求地址
method: ‘’, // 请求方式 GET/POST/PUT/DELETE
params: {}, // GET/DELETE 请求的 query 参数
data: {}, // POST 或 DELETE 请求的请求体参数
} - 响应 json 数据自动解析为 js
代码实现:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<div>
<button onclick="testGet()">GET 请求</button>
<button onclick="testPost()">POST 请求</button>
<button onclick="testPut()">PUT 请求</button>
<button onclick="testDelete()">DELETE 请求</button>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/axios/0.24.0/axios.js"></script>
<script>
/*
使用 XHR 封装发送 ajax 请求的通用函数
返回值: promise
参数为配置对象
url: 请求地址
params: 包含所有 query 请求参数的对象 {name: tom, age: 12} ==> name=tom&age=12
data: 包含所有请求体参数数据的对象
method: 为请求方式
*/
function axios({ url, method = "GET", params = {}, data = {} }) {
// 返回一个promise对象
return new Promise((resolve, reject) => {
// 处理method(转大写)
method = method.toUpperCase();
// 处理query参数(拼接到url上) id=1&xxx=abc
/*
{
id: 1,
xxx: 'abc'
}
*/
let queryString = "";
Object.keys(params).forEach((key) => {
// queryString += `${key}=${params[key]}&`;
queryString += key + "=" + params[key] + "&";
});
if (queryString) {
// id=1&xxx=abc&
// 去除最后的&
queryString = queryString.substring(0, queryString.length - 1);
// 接到url
url += "?" + queryString;
}
// 1. 执行异步ajax请求
// 创建xhr对象
const request = new XMLHttpRequest();
// 打开连接(初始化请求, 没有请求)
request.open(method, url, true);
// 发送请求
if (method === "GET" || method === "DELETE") {
request.send();
} else if (method === "POST" || method === "PUT") {
request.setRequestHeader(
"Content-Type",
"application/json;charset=utf-8"
); // 告诉服务器请求体的格式是json
request.send(JSON.stringify(data)); // 发送json格式请求体参数
}
// 绑定状态改变的监听
request.onreadystatechange = function () {
// 如果请求没有完成, 直接结束
if (request.readyState !== 4) {
return;
}
// 如果响应状态码在[200, 300)之间代表成功, 否则失败
const { status, statusText } = request;
// 2.1. 如果请求成功了, 调用resolve()
if (status >= 200 && status <= 299) {
// 准备结果数据对象response
const response = {
data: JSON.parse(request.response),
status,
statusText,
};
resolve(response);
} else {
// 2.2. 如果请求失败了, 调用reject()
reject(new Error("request error status is " + status));
}
};
});
}
function testGet() {
axios({
url: "http://localhost:3000/comments",
// url: 'http://localhost:3000/comments2',
params: { id: 3 },
})
.then((response) => {
console.log("get success", response.data, response);
})
.catch((err) => {
alert(err.message);
});
}
function testPost() {
axios({
url: "http://localhost:3000/comments",
// url: 'http://localhost:3000/comments2',
method: "POST",
data: { body: "aaaa", postId: 2 },
})
.then((response) => {
console.log("post success", response.data, response);
})
.catch((error) => {
alert(error.message);
});
}
function testPut() {
axios({
url: "http://localhost:3000/comments/3",
method: "put",
data: { body: "ndkasj", postId: 2 },
})
.then((res) => {
console.log("put success", res.data, res);
})
.catch((err) => {
alert(err.message);
});
}
function testDelete() {
axios({
url: "http://localhost:3000/comments/1",
method: "delete",
params: {
body: "some comment",
},
})
.then((response) => {
console.log("delete success", response.data, response);
})
.catch((error) => {
alert(error.message);
});
}
</script>
</body>
</html>