Axios快速上手
目录
1 Axios简介
2 Axios安装
3 Axios简单使用
4 Axios进阶使用
4.1 全局统一配置
4.2 导出axios实例
4.3 拦截器
4.3.1 请求拦截器
4.3.2 响应拦截器
5 Axios项目使用
5.1 跨域问题
5.1.1 同源策略与跨域问题
5.1.2 跨域问题解决方案
5.2 代理服务器
5.2.1 三种常见场景的跨域问题
5.2.2 代理服务器配置
5.3 封装使用流程
5.3.1 axios实例封装
5.3.2 代理服务器封装
5.3.3 请求接口方法封装
1 Axios简介
Axios是一个基于promise( Promise是JavaScript的异步编程的对象,用来接收异步操作成功或失败以及数据的对象)的网络请求库,可用于node.js和浏览器中。用于node.js就是后端开发发送http请求,用于浏览器就是前端开发发送ajax请求。
Aaxios(ajax i/o system)本质上也是对原生XHR(XMLHttpReques)的封装,只不过它是基于promise的,是promise的实现版本,符合最新的ES规范。
Axios作为请求库,具有如下优势:
- 标准化:统一浏览器/Node环境请求接口。
- 拦截器机制:可拦截请求/响应,实现全局逻辑(如Token注入、错误处理)。
- 自动转换:请求/响应数据自动转为JSON,支持自定义转换逻辑。
- 取消请求:通过CancelToken中止长时间未响应的请求。
2 Axios安装
终端打开项目地址,输入如下命令:
npm install axios # Node 环境
3 Axios简单使用
要使用Axios,首先需要引入axios包,然后通过create()创建axios实例,才能使用:
import axios from 'axios'
// GET 请求(参数自动拼接到 URL)
axios.get('/user', { params: { id: 123 } }).then(res => console.log(res.data)) .catch(err => console.error(err)); // POST 请求(自动序列化 JSON)
axios.post('/login', { username: 'admin', pwd: '123' }).then(res => console.log(res));
上述通过引入axios,使用get发送GET请求,使用post发送POST请求,通过Promise对象的.then和.catch等链式调用的方式来获取成功态的Promise实例和拒绝态的Promise实例(失败)。
除了get和post请求,还有其它请求方式:
- get:获取数据
- post:提交数据(表单提交与文件上传)
- patch:更新数据(只将修改的数据推送到后端(服务端))
- put:更新数据(所有数据推送到服务端)
- delete:删除数据
4 Axios进阶使用
上述使用方式特点是功能简单,并且只能在单个组件中使用,如果要全局使用,就可以创建Axios实例并导出,灵活配置后端URL:
4.1 全局统一配置
全局统一配置Axios实例一般需要单独创建js文件,在其中创建Axios实例并导出:
// 创建 axios 实例
const instance = axios.create({//后端服务器ip地址baseURL: import.meta.env.VITE_APP_BASE_API,timeout: 600000
})
baseURL参数是后端服务器的ip地址,timeout是超时时间。
建议:后端服务器ip地址不要写死,根据环境变量或常量进行灵活动态变化。
4.2 导出axios实例
通过export导出默认的axios实例,接收5个参数:
// 导出自定义请求函数(url是接口地址(因为基本ip地址已经封装,只需接口地址再拼接即可)、请求类型、数据、参数、请求头)
export default ({ url, method, data, params, header }) => {return instance({url,method,data,params,header})
}
要使用axios实例的组件需要导入该实例,并传入url(接口地址)、method(请求方法)、data(发送的数据)、params(请求参数)、header(请求头),即可发送请求。
接口地址会被自动拼接到后端服务器ip后从而发送完整的请求路径。
4.3 拦截器
可以在创建axios实例后,对实例添加拦截器,然后在请求发送前和响应接收前做一些特殊处理(公共处理:每个接口都需要进行步骤,比如用户鉴权Token)。
4.3.1 请求拦截器
请求拦截器在请求发送前进行拦截请求,并处理一些事情,比如请求头添加Token:
// 添加请求拦截器
instance.interceptors.request.use((config) => {// config就是和此次请求相关的信息,包含请求地址,方法,参数,头等const userStore = useUserStore()const { token } = userStore// 如果有Token,说明已经登录过,所有的登录后请求头应该添加Tokenif (token) {config.headers.Authorization = token}// 必须返回config,否则无法获取响应数据return config},(error) => {// 对请求错误做些什么return Promise.reject(error)}
)
4.3.2 响应拦截器
响应拦截器是在响应被处理前进行拦截,可以对响应数据进行状态码验证、数据解构等操作:
// 添加响应拦截器
instance.interceptors.response.use((response) => {// 解构:从响应response对象的data属性才能拿到后端返回的数据const { code, data, msg } = response.dataif (code !== 200000) {// 返回一个失败态的 Promise 实例// 拦截器后的接口请求方就会收到错误的Promise实例,即被.catch到return Promise.reject(new Error(msg))}// 否则返回纯粹的 data 数据return data},(error) => {// 所有的接口响应失败都必须先执行这里const { response, status } = error//比如http状态是401if (status === 401) {// token 过期// TODO相应的一些关于token删除的操作// 返回拒绝态的Promise实例return Promise.reject(new Error('token过期'))} else {// 其它失败状态const { code, msg } = response.data// 返回失败态的Promise实例,并携带错误信息return Promise.reject({code,msg})}}
)
5 Axios项目使用
前端在开发过程中,如果直接使用axios发送请求,大概率出现跨域问题,要了解跨域问题和解决方案,首先就需要了解同源策略:
5.1 跨域问题
5.1.1 同源策略与跨域问题
(1)同源策略
首先声明同源策略是浏览器的行为策略。
同源策略:同源是指浏览器发出的请求所访问的服务器的url协议一样、域名一样、端口号一样,三者都一样则称为同源。
(2)跨域问题
跨域问题:同源的三个条件只要有一个不一样就是跨域,这是浏览器禁止的行为,浏览器出于安全考虑,采用同源策略,不允许跨域请求。
理解跨域问题的核心是理解浏览器发送请求的行为流程:这里的浏览器的同源策略是对前端JS代码的约束,浏览器通过地址栏输入URL访问前端静态资源是允许的。而浏览器获取从前端服务器获取到的静态资源中,JS部分访问后端服务器(不同源,和浏览器访问前端资源的URL至少端口号或域名不一样),因此才会发生跨域问题。
比如:浏览器请求前端服务器路径http://localhost:5173,前端服务器的js代码请求后端服务器路径http://localhost:8080,两者端口号不同,因此不满足同源策略。当然这种情况是前端服务器和后端服务器都部署在一台主机上,使用端口号不同。
5.1.2 跨域问题解决方案
(1)CORS:后端开启跨域资源共享,前端不需要做什么事。
(2)请求代理:浏览器访问本地服务器(这也不涉及跨域,因为这是浏览器地址栏URL的基础导航功能,并且自己访问自己凭什么不可以),由本地服务器访问后端服务器,服务器之间不存在跨域问题(因为请求链不涉及浏览器)。
5.2 代理服务器
5.2.1 三种常见场景的跨域问题
传统前后端还未完全分离的项目中,静态资源存储在后端服务器中,浏览器从后端服务器获取静态资源,静态资源中JS代码部分请求后端服务器,因此浏览器请求的URL和后端服务器URL是同源的(同协议、同域名、同端口),只是数据接口的路由地址不同,因此不存在跨域问题。
前后端分离项目,如果未配置跨域请求代理,前端静态资源部署在前端服务器中(Node服务器),浏览器请求前端静态资源,请求的URL是前端服务器的URL,而静态资源的JS部分请求的是后端服务器URL,如果前端服务器和后端服务器在同一个主机上,由于至少端口号不同,因此不同源,即发生跨域问题;如果前端服务器和后端服务器不在同一台主机上,那至少域名不相同(ip),因此也会发生跨域问题。
如果配置跨域请求代理,代理服务器也是前端服务器(仅需添加配置项),因此浏览器请求前端服务器获取静态资源,JS部分请求跨域请求代理,由跨域请求代理转发请求(服务器之间访问不存在浏览器同源策略的限制),此时就不会发生跨域问题。
5.2.2 代理服务器配置
export default defineConfig({// 开发服务器配置server: {port: 80, // 端口open: true, // 自动打开浏览器// 配置跨域请求代理proxy: {'/dev-api': {// 目前服务器地址(目前开发阶段暂时用本地ip+端口号模拟,实际应该用后端服务器的ip地址+端口号)target: 'http://127.0.0.1:18081',changeOrigin: true, // 改变请求头的origin源,保证到达后端服务器的值是target值而不是前端请求路径// 路径重写:不进行重写,请求到达后端就是:服务器地址+/dev-api+请求的接口地址// 如果后端服务器的接口地址没有/dev-api,就会请求不到资源,因此需要替换为空字符串rewrite: (path) => path.replace(/^\/dev-api/, '')}}}
})
在vite.config.js中配置Node服务器server,port是前端服务器的端口,open是启动项目自动打开首页策略。
proxy是跨域请求代理的配置项,配置转发路由为/dev-api,target是后端服务器地址,changeOrigin为true表示改变请求头的origin源,确保后端接收的请求的目标URL是后端服务器的值而不是前端发出的值。rewrite表示对路径进行重写,去除/dev-api路由。
即完整的流程如下:
(1)前端服务器位于http://localhost:80,浏览器请求静态资源的URL为http:localhost:80/example/api(前端服务器地址+JS请求后端的接口路由)。
(2)JS部分的Axios在请求路径添加http:localhost:80/dev-api/example/api发送到代理服务器(Node服务器监听80端口,如果请求路径是/dev-api,则由代理服务器处理该URL)。
(3)后端服务器位于http://localhost:18081,代理服务器重写请求URL为http://localhost:18081/example/api并转发该请求,因此解决跨域请求问题。
5.3 封装使用流程
由于Axios的使用流程比较固定,且每个前端涉及到请求后端的项目中都需要上述配置,因此可以对这部分进行封装,所有的项目都可以按照统一流程处理和使用:
5.3.1 axios实例封装
创建js文件,配置如下内容:
(1)导入Axios并创建实例:即全局统一配置部分;
(2)配置实例的拦截器;
(3)导出Axios实例。
5.3.2 代理服务器封装
即5.2.2代理服务器配置部分,在vite.config.js文件添加。
5.3.3 请求接口方法封装
创建api包,内部放js文件,文件内容是发送请求的方法。比如登录请求:
export const loginApi = ({ phone, password }) => {return request({method: 'post',url: '/admin/sys_user/login/password',data: {phone,password}})
}
使用该方法就在对应的组件中导入该方法,传入参数即可发送请求。