异步编程(axios)
- 基本介绍
Axios 是基于 Promise 封装的 HTTP 客户端库,可在浏览器和 Node.js 中使用;支持 GET(获取)/POST(提交)/PUT(更新)/DELETE(删除)等请求,自带请求 / 响应拦截器、自动转换 JSON、超时配置、取消请求、请求头统一设置,解决原生 Ajax 回调地狱问题,是前端主流网络请求方案。 - 引入方式
<script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
- 核心语法
(1)GET 请求(获取数据)
axios({
method: 'get',
url: '接口地址',
params: { // 会拼在 ? 后面
name: 'zs',
age: 18
}
}).then(result => {
console.log(result.data) //成功执行
}).catch(error => {
console.log(error) //失败执行
})
简写:
axios.get('url', { params: {} })
(2)POST 请求(提交数据)
axios({
method: 'post',
url: '接口地址',
data: { // 数据
username: 'zs',
password: '123456'
}
})
简写:
axios.post('url', { 数据 })
- 接口文档 = 前后端约定的 “通信协议”
前端按照文档发请求,后端按照文档返回数据。
- 请求报文
请求行(方式 路径 协议版本)
请求头(类型 格式 token)
空行
请求体 payload
请求参数的 3 种格式:
1.查询参数 (GET 专用)
拼接在 URL 后面:?name=zs&age=18
axios 用 params:{}
2.请求体参数 body(POST 专用)
放在请求体,不显示在 URL
axios 用 data:{}
格式:application/json
前端叫 data,网络控制台里叫 Payload,后端接收叫 Body
3.路径参数
嵌在 URL 路径中间
例如:/api/user/123
123 是路径参数
axios 用 axios.get(/api/user/${id})
- 响应报文(响应头、响应体)
状态行(协议版本 状态码 / 错误码)
响应头 (类型 格式)
响应体 JSON 格式
HTTP 状态码
1001 用户名不存在
1002 密码错误
200 成功
201 创建成功
400 参数错误
401 未登录 /token 过期
403 无权限
404 接口不存在
500 服务器报错
-
响应结果
result.data → 真正后端返回的数据
result.status → 状态码 2成功 4失败
result.headers → 响应头
result.config → 请求配置
error.response.data.message →后端返回的错误信息 -
URL /params/data 区别
url:接口地址 (协议://域名/资源路径)
params:{名:值},GET 用,拼接在地址 ?后,?key=value&key=value。 属性名与值相同时,可以只写一个
data:用于 POST/PUT,参数放在请求体 payload 里 -
表单数据处理
(1)单个表单
const username = document.querySelector('#username').value
(2)多个表单(使用 form-serialize)
const data = serialize(表单DOM, {
hash: true, // 转成 JS 对象
empty: true // 允许获取空值
})
const { username, password } = data//解构
//表单每一个输入框的 name 属性值,必须和后端接口文档的字段名一模一样。
- Promise (Axios 底层依赖)
Axios 是基于 Promise 封装
解决回调地狱,嵌套转为链式
支持 .then() .catch()
支持 Promise.all() 并发请求 - async /await 写法(最优雅!)
async function getData() {
try {
const result = await axios({ url: 'xxx' })
console.log(result.data)
} catch (error) {
console.log('请求失败', error)
}
}
await获取promise对象成功状态值,代替.then回调函数,原地等待结果
await 必须写在 async 函数里
try/catch 捕获错误
try里某行代码错误,剩余代码不执行
代码像同步一样,非常清晰
- 并发请求(多个接口一起发)
const p1 = axios.get('url1')
const p2 = axios.get('url2')
Promise.all([p1, p2]).then(result => {
console.log(result[0].data)
console.log(result[1].data)
}).catch(err => {
console.log('有一个失败就失败')
})
- Token 认证(登录必备)
判断有无登录状态,有无权限。
前端判断有无,后端通过解密判断有效性
//登录成功后保存 token
localStorage.setItem('token', result.data.token)
//请求时携带 token(放在请求头)
axios.defaults.headers.common.Authorization = 'Bearer ' + token
//判断是否登录
const token = localStorage.getItem('token')
if (!token) {
location.href = 'login.html'
}
- Axios defaults 全局配置
axios.defaults.baseURL = 'http://localhost:3000'
axios.defaults.timeout = 5000//超时时间
以后写:
axios.get('/api/user')
- 拦截器
请求拦截(请求发出去之前统一处理)
axios.interceptors.request.use(config => {
// 在发送请求之前 有公共配置时使用
//发送前做什么:加token、加载提示
const token = localStorage.getItem('token')
if (token) {
config.headers.Authorization = `Bearer ${token}`
}
return config
},err => {
// 统一错误处理
return Promise.reject(err)
})
响应拦截(对响应结果统一处理)
axios.interceptors.response.use(res => {
// 2xx 范围内的状态码都会触发该函数
return res.data // 直接返回data,不用每次写res.data
}, err => {
// 统一错误处理
// 超出 2xx 范围的状态码都会触发该函数
if(error?.response?.status === 401){
//401 未授权:Token 过期 / 没带 Token,清空本地 Token,跳转到登录页。
alert('登录状态过期')
localStorage.clear()
location.href= ''
}
return Promise.reject(err)
//403 禁止访问:登录成功但无权限,提示无权限访问。
})
-
事件循环 / 宏任务微任务(Axios 执行顺序)
先执行同步代码(promise里的是同步,acync整体同步)
再执行微任务(js引擎执行的异步代码,如Promise.then,await后续)
最后执行宏任务(浏览器执行的异步代码,如定时器、AJAX、事件) -
封装函数核心思想:什么不同,传入什么
重复不变的代码写在函数内部
每次不一样的(地址、参数、请求方式)当成形参传入 -
Bootstrap 弹框
<!-- 按钮:自定义属性 data-bs-toggle、data-bs-target -->
<button data-bs-toggle="modal" data-bs-target="#myModal">
打开弹框
</button>
<!-- 弹框 -->
<div class="modal" id="myModal">
<div class="modal-dialog">
<div class="modal-content">
弹框内容
</div>
</div>
</div>
17.异步编程
->回调函数:原生异步,回调地狱,可读性差;
->事件监听
->Ajax:异步 JavaScript + XML,写法繁琐。核心是浏览器通过 JS 异步向服务器发请求,获取数据后局部刷新页面,不用整页刷新。通过 open、设置监听、send 三步完成请求
->axios:XML 的 Promise 封装,解决回调地狱,链式调用,自带拦截器。
->Fetch 是浏览器原生新标准、基于 Promise,但错误处理不友好、功能简陋,需自行封装。
->Generator/yield:分段控制异步,偏底层;
->async/await:Promise 语法糖,以同步化写法简化异步代码,结构扁平,同时保留 Promise 所有能力,项目首选;
->Web Worker:多线程,处理密集计算。
- 原生 AJAX 实现
const xhr = new XMLHttpRequest();
// 1. 初始化:请求方法、URL、是否异步
xhr.open('GET', '/api/data', true);
// 2. 设置请求头(POST 时需要)
xhr.setRequestHeader('Content-type', 'application/json');
// 3. 监听状态变化
xhr.onreadystatechange = function () {
// 请求完成
if (xhr.readyState === 4) {
// 状态码 200~299 成功
if (xhr.status >= 200 && xhr.status < 300) {
const res = JSON.parse(xhr.responseText);
console.log('成功', res);
} else {
console.log('失败', xhr.status);
}
}
};
// 4. 发送请求
xhr.send();
// POST 这么用:xhr.send(JSON.stringify(data))
-
fetch使用
fetch(‘/api/data’)
.then(res => res.json())
.then(data => console.log(data))
.catch(err => console.error(err)) -
封装ajax
function ajax({
url,
method = 'GET',
data = null,
headers = {}
}) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
// 打开请求
xhr.open(method.toUpperCase(), url, true)
// 设置请求头
Object.keys(headers).forEach(key => {
xhr.setRequestHeader(key, headers[key])
})
// 监听响应
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
let res
try {
res = JSON.parse(xhr.responseText)
} catch (e) {
res = xhr.responseText
}
resolve(res)
} else {
reject(new Error(`请求失败,状态码:${xhr.status}`))
}
}
// 网络错误
xhr.onerror = function () {
reject(new Error('网络异常或请求被终止'))
}
// 发送数据
if (data && typeof data === 'object') {
xhr.send(JSON.stringify(data))
} else {
xhr.send(data)
}
})
}
// GET
ajax({ url: '/api/user' })
.then(res => console.log(res))
.catch(err => console.error(err))
// POST
ajax({
url: '/api/login',
method: 'POST',
data: { username: 'admin', password: '123456' },
headers: { 'Content-Type': 'application/json' }
})
AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。
更多推荐
所有评论(0)