提示:文章为 学习过程中的记录实践笔记。有问题欢迎指正。
文章目录
前言
AJAX 不是编程语言,是一种从网页访问web服务器的技术。
可以实现不刷新页面更新网页
在页面加载后从服务器请求/获取数据
在后台向服务器发送数据
AJAX 等价于 Asynchronous JavaScript And XML.
一、实现步骤
- 创建 XMR
XMLHttpRequest()
javascript
const xhr = new XMLHttpRequest();
- 配置请求
open(method,url,async,user,psw)
参数说明: 请求方式,请求地址,是否异步,可选的用户名,可选的密码
- get 偏向 获取数据
- post 提交数据
- put 更新(全部)数据
- delete 删除数据
- patch 部分修改
请求方式 method | 是否异步 |
---|---|
GET,POST,PUT,DELETE 等 | true(异步) false(同步) |
javascript
xhr.open('GET', 'http://localhost:5500/javascript/ajax/data.json')
- 发送请求
send()
javascript
xhr.send();
- 接收请求 - 定义接收到(加载)请求时调用的函数
onload
当请求完成时会被调用
javascript
xhr.onload = function(){
//处理返回值
}
onreadystatechange
当readyState属性发生变化时调用
二、完整示例
使用 onload 接收数据

使用 onreadystatechange
readyState
不同状态
0:请求未初始化
1:服务器连接已建立
2:请求已收到
3:正在处理请求
4:请求已完成且响应已就绪
javascript
xhr.onreadystatechange = function () {
// console.log(xhr.readyState, xhr.status)
// 接收状态码 4:解析完成 http状态码 200~299 都是正确的 常见 200
if (xhr.readyState === 4 && xhr.status === 200) {
console.log('数据解析完成', xhr.responseText)
} else if (xhr.readyState === 4 && xhr.status === 404) {
console.log('请求地址不存在')
}
}
模拟后端接口数据
ajax涉及到与后端接口数据的交互,方便模拟交互可以使用json-server
工具
json-server 可用于快速mock一个 REST API 服务器,让开发者能够专注于前端开发,同时轻松模拟后端 API,提高了开发效率和测试的准确性。
安装json-server
- 全局安装
bash
npm install -g json-server
- 测试是否成功
bash
json-server -v
//或者
json-server --version
- 创建json 文件
json文件结构
文件中 user相当于是一个 user表,里面的字段,就是表中存储的字段
json
{
"user": [
{ "id": 1, "name": "Anan" }
],
"comments": [
{ "id": 1, "body": "some comment", "userId": 1 }
]
}
- 启动服务
data.json 是要监听的json模拟文件路径
--port 是指定端口号,省略则自动启动默认端口号
bash
json-server --watch data.json --port 3000
在发送请求的时候,直接请求文件
获取到的返回值 就是整个json文件中的内容

三、封装AJAX
javascript
//ajax.js
function ajax(option) {
const options = {
method: 'GET',
url: '',
data: '',
success: function () { },//成功回调函数
error: function () { },
...option,
}
const xhr = new XMLHttpRequest();
const method = options.method.toUpperCase();
const url = options.url;
let data = null;
if (option.data) {
data = Object.keys(options.data).map(key => key = options.data[key]).join('&');
}
if (method === 'GET' && data) {
url += '?' + data;
}
xhr.open(method, url);
if (method === 'POST') {
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
}
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status >= 200 && xhr.status < 300) {
const response = xhr.getResponseHeader('Content-Type').includes('json') ? JSON.parse(xhr.responseText) : xhr.responseText;
options.success && options.success(response);
} else {
options.error && options.error(xhr.status);
}
}
};
xhr.send(method === 'POST' ? data : null);
}
export default ajax;
调用封装

回调地狱
当我们封装了ajax 创建了回调函数 success 和 error
如果我们有多个请求,需要在 前一个请求之后,拿到上一个成功之后的结果,或等待上步成功后执行,会涉及到多次调用
例如:下图中代码,被称为 回调地狱 涉及多层嵌套,不便于维护

四、Promise
Promise()是构造函数
该构造函数主要用于封装还没有添加 promise 支持的函数。
代表了一个异步操作的最终完成或者失败
Promise的出现 是为了解决回调地狱出现的
- 一个 Promise 必然处于以下几种状态之一:
待定(pending) | 已兑现(fulfilled) | 已拒绝(rejected) |
---|---|---|
初始状态,既没有被兑现,也没有被拒绝。 | 操作成功 | 操作失败 |
- promise基本用法
promise 有两个回调 resolve 和 reject,对应 then 和 catch
pro.then((res) =>{})
接收到的是成功的回调结果。
通过在 new Promise((resovle,reject) => {})
中执行逻辑
成功的时候,将结果 resolve(res)
此时 .then() 接收成功值;
若 失败 rejecte(res)
此时 **.catch()**接收失败信息
示例如下:
javascript
const pro = new Promise((resolve, reject) => {
// 异步执行
setTimeout(() => {
console.log('执行某些操作')
// promise 的兑现值
// resolve('执行成功');
reject('执行失败')
}, 2000)
})
//对应第一个回调函数参数 resolve
pro.then((res) => {
console.log(res)//执行成功
})
//对应第二个回调函数参数 reject
pro.catch((res) => {
console.log(res)//执行失败
})
如果需要处理多个逻辑,并且需要得到上一步的执行成功返回结果,可以通过链式.then
对失败结果,做统一处理
javascript
doSomething()
.then((result) => doSomethingElse(result))
.then((newResult) => doThirdThing(newResult))
.then((finalResult) => {
console.log(`最终结果:${finalResult}`);
})
.catch(failureCallback);
- Promise.all() 当有多个异步函数需要等待并发执行时 ,可以使用
Promise.all()
js
const evt1 = new Promise((resolve,reject) =>{})
const evt2 = new Promise((resolve,reject) =>{})
// 等待两个事件执行结束后
Promise.all([evt1,evt2]).then(res =>{
// 全都成功执行
}).catch(err => {
// 执行失败
})
五、 async/await
对于上面的 promise 虽然解决了回调地狱的问题,但如果逻辑过多,会有链式过长,也不够优雅。
所以 又有了 async/await 的方式
对于上面封装的 ajax 可以 换种方式,封装为 异步函数
当执行成功时,兑现成功回调,失败则相反

- 使用方式
async 和 await 必须配套使用。
如果 请求 使用await 请求的方法必须是 异步 asyn

如上图,此时在等待接口返回结果时,可以直接在赋值 const res = await asyncAjax()
接收返回值
Fetch
fetch 是一个封装的对象,功能以前是使用 XMLHttpRequest 实现的
- fetch() 收到一个代表错误的 HTTP 状态码时,fetch() 返回的 Promise 不会被标记为 reject,即使响应的 HTTP 状态码是 404 或 500
- 相反,它会将 Promise 状态标记为 resolve
(如果响应的 HTTP 状态码不在 200 - 299 的范围内,则设置 resolve 返回值的 ok 属性为 false) - 仅当网络故障时或请求被阻止时 ,才会标记为 reject
fetch使用案例

- fetch() 结合async/await

总结
通俗的说,就像是拨打电话,
- 首先要拿起电话
new XMLHttpRequest()
- 打开通讯录拨号/查看通讯录
open(method,url)
\ - 点击拨打
send()
- 等待接通
onreadystatechange
|| 接通后onload