个人博客-SpringBoot+Vue3项目实战(6)- 二次封装Axios

news/2024/11/7 22:46:13/

目录

  • 前言
  • 新建axiosUtil.js 文件
  • 基本配置
    • 统一URL
      • `.env`文件与环境变量
      • 示例
      • 参考资料
    • 请求头
    • 超时时间
  • request 拦截器
  • response 拦截器
  • 统一Api管理
  • 测试

前言

在上文中,我们封装了统一的后端数据返回结果,有了标准化的接口数据,我们就可以针对它,在前端发送接收时,进行预处理。

通常在一个企业级或者个人开源的项目中,Axios会被二次封装。

二次封装的好处有哪些呢?

  1. 统一 url 配置
  2. 统一 api 请求
  3. request (请求)拦截器,例如:带上token等,设置请求头
  4. response (响应)拦截器,例如:统一错误处理,页面重定向等
  5. 统一处理http错误码code错误码

新建axiosUtil.js 文件

话不多说,我们直接开始吧!

创建src\utils\axiosUtil.js

这个文件就是用来封装Axios,我们想要在其他文件中使用Axios,这里我们就需要创建并抛出一个Axios实例。

import axios from 'axios'
import { ElMessage , ElNotification  } from 'element-plus'let axiosUtil = axios.create({
})export default axiosUtil;

接下来,我们就开始进行配置。打开http://axios-js.com/zh-cn/docs/index.html#请求配置查看Axios提供的配置项。

基本配置

统一URL

首先,我们需要配置的是统一的请求接口。我们在测试test接口时直接使用AxiosGET请求http://localhost:8080/test,这里的http://localhost:8080/就是一个统一的Url。

image-20230130135606188

let axiosUtil = axios.create({baseURL:'http://localhost:8080',
})

有了这个baseURL在发送post请求的时候,就不需要加上http://localhost:8080/,Axios会自动给我们加上!!!

.env文件与环境变量

但是http://localhost:8080/这个只是本地测试的接口,我们还有服务器测试接口,上线后的接口。针对不同接口,我们每次都需要修改,是一件很麻烦的事情,还好我们使用的是Vite作为的辅助开发工具。

Vite 使用 dotenv 从你的 环境目录 中的下列文件加载额外的环境变量:

.env                # 所有情况下都会加载
.env.local          # 所有情况下都会加载,但会被 git 忽略
.env.[mode]         # 只在指定模式下加载
.env.[mode].local   # 只在指定模式下加载,但会被 git 忽略

这里的模式通常包含:

  • test 测试
  • development 开发
  • production 生产
  • staging 预发布
  • 其他

也就是说我们需要在根目录下新建对应的**.env**文件

  • .env.test
  • .env.development
  • .env.production
  • .env.staging

大家打开package.json文件,会看到以下命令

 "scripts": {"dev": "vite","build": "vite build","preview": "vite preview"},

当我们在命令行执行yarn dev yarn run dev,其实是执行vite

默认情况下,dev 命令 运行在 development (开发) 模式,而 build 命令和preview命令则运行在 production (生产) 模式。

 "scripts": {"dev": "vite --mode development","build": "vite build --mode production","preview": "vite preview --mode production "},

在**.env**文件中,我们可以编写额外的环境变量。为了防止意外地将一些环境变量泄漏到客户端,只有以 VITE_ 为前缀的变量才会暴露给经过 vite 处理的代码。

例如:

VITE_APP_TITLE= 个人博客
VITE_APP_BASE_API= 'http://localhost:8080'

当我们执行命令的时候,Vite 暴露环境变量到一个特殊的 import.meta.env 对象上。我们可以通过这个对象来获取编写的环境变量。

image-20230206091542335

示例

新建.env文件

VITE_APP_TITLE= 个人博客
VITE_APP_BASE_API= 'http://localhost:8080'

我们刚才说了,import.meta.env挂着我们编写的环境变量。

我们修改axiosUtils

let axiosInstance = axios.create({baseURL:import.meta.env.VITE_APP_BASE_API,
})

参考资料

https://cn.vitejs.dev/guide/env-and-mode.html#env-variables

请求头

我们后端支持支持什么格式的数据,这里就可以指定具体的Content-type。我们这个项目就指定json即可

import axios from 'axios'
import { ElMessage , ElNotification  } from 'element-plus'import axios from "axios"
let axiosUtil = axios.create({baseURL:import.meta.env.VITE_APP_BASE_API,headers:{"Content-type":"application/json"}
})

超时时间

一个请求超过一段时间自动停止。

import axios from 'axios'
import { ElMessage , ElNotification  } from 'element-plus'let axiosUtil = axios.create({baseURL:import.meta.env.VITE_APP_BASE_API,headers:{"Content-type":"application/json"}timeout: 10000,
})

request 拦截器

在请求发出之前,抽离出共同的方法。

例如 对于所有的psot请求,我们可能需要去进行序列化参数(后端要求序列化的参数),

又例如,我们发送的请求是错误的,我们要如何处理。

又又例如:我们的请求接口是需要token的,但是登录的接口不需要,此时我们在请求时就需要拦截,给除了登录接口之外的其他接口加上token。

参考官网的写法http://axios-js.com/zh-cn/docs/index.html#%E6%8B%A6%E6%88%AA%E5%99%A8

例如,我们使用的restful风格的接口,我们需要将get请求的参数拼接到URL上,那我们就可以在发送请求之前进行拼接。

// request拦截器
axiosUtil.interceptors.request.use(config => {// get请求映射params参数if (config.method === 'get' && config.params) {let url = config.url + '?';for (const propName of Object.keys(config.params)) {const value = config.params[propName];const part = encodeURIComponent(propName) + '='if (value !== null && typeof (value) !== "undefined") {if (typeof value === 'object') {for (const key of Object.keys(value)) {let params = propName + '[' + key + ']';const subPart = encodeURIComponent(params) + '='url += subPart + encodeURIComponent(value[key]) + "&";}} else {url += part + encodeURIComponent(value) + "&";}}}url = url.slice(0, -1);config.params = {};config.url = url;}return config
}, error => {console.log(error)Promise.reject(error)
})

response 拦截器

在接收到请求之后,抽离出共同的方法。

例如: 接口400怎么办,接口500怎么办!

又例如 :接收到的数据怎么办!

axiosUtil.interceptors.response.use(async res => {// 未设置状态码则默认成功状态const code = res.data.code || 200;// 获取错误信息const msg = res.data.msg if (code === 500) {ElMessage ({message: msg,type: 'error'})return Promise.reject(new Error(msg))} else if (code = 401) {// TODO console.log("重新登录,重定向登录页面")return Promise.reject('error')} else if (code !== 200) {ElNotification .error({title: msg})return Promise.reject('error')} else {return res.data}
}, error => {console.log('err' + error)let { message } = error;if (message === "Network Error") {message = "后端接口连接异常";} else if (message.includes("timeout")) {message = "系统接口请求超时";} else if (message.includes("Request failed with status code")) {message = "系统接口" + message.substr(message.length - 3) + "异常";}ElMessage ({message: message,type: 'error',duration: 5 * 1000})return Promise.reject(error)
}
)

统一Api管理

对于同一个模块的请求我们通常是放在封装在一个文件夹里。例如这里的测试,我会新建src\api\test.js文件。

在这个文件里,编写涉及到测试的增删改查接口。

import axiosUtil from '../utils/axiosUtil.js'class TestApi{create(data){console.log(data)return axiosUtil.get('/test')}delete(data){// 方法体内}}
export default new TestApi();

测试

src/App.vue我们重写reqTest方法。

 import TestApi from './api/test'const reqTest = () => {TestApi.create().then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});
}

不启动后端,直接在前后发送请求,10000毫秒之后会弹出后端接口连接异常的消息

image-20230206100328515


http://www.ppmy.cn/news/99889.html

相关文章

[golang 微服务] 2. RPC架构介绍以及通过RPC实现微服务

一.简介 在上一节简单了解了微服务定义和优缺点之后,在使用微服务框架之前,需要首先了解一下RPC架构,通过RPC可以更形象了解微服务的工作流程 RPC的概念 RPC(Remote Procedure Call Protocol),是 远程过程调用的缩写,通俗的说就是…

复合查询.

基本查询 查询工资高于500或岗位为MANAGER的雇员,同时还要满足他们的姓名首字母为大写的J select * from EMP where (sal>500 or jobMANAGER) and ename like J%;按照部门号升序而雇员的工资降序排序 select * from EMP order by deptno, sal desc;使用年薪进…

SpringBoot AOP切面编程 使用案例

参考资料 Springboot AOP实现指定敏感字段数据加密 (数据加密篇 二)【SpringBoot-3】切面AOP实现权限校验:实例演示与注解全解【小家Spring】Spring AOP中Pointcut切入点表达式最全面使用介绍AOP编程过程中的Signature接口 本篇文章核心思想…

C919用了哪些人工智能(AI)技术?

#国产大飞机C919商业首飞#近日,C919在国人的期盼下终于迎来了首次商飞,机票已公开售卖。众所周知,C919是一款全新的、先进的大飞机,那你知道它采用了哪些新的人工智能(AI)技术吗?下面让我来为大…

[Kubernetes] - RabbitMQ学习

1.消息队列 消息: 在应用间传送的数据队列,先进先出 1.2. 作用 好处:解耦, 容错,削峰坏处:降低系统可用性,系统复杂度提高,一致性问题; RabbitMQ组成部分&#xff1a…

4.7 小结

4.7 小结 以上就是局域网的所有知识,我们学习了局域网的基本概念、体系结构、工作原理,根据所采用的技术不同局域网分成了多种类型,包括了IEEE 802.3局域网,令牌环网、令牌总线网、IEEE 802.11无线局域网,我们学习了各…

【C++/嵌入式笔试面试八股】一、32.封装

封装 08.C++中struct和class的区别🍊 相同点 两者都拥有成员函数、公有和私有部分任何可以使用class完成的工作,同样可以使用struct完成不同点 两者中如果不对成员不指定公私有,struct默认是公有的,class则默认是私有的class默认是private继承, 而struct默认是public继…

【线程池】Executors框架创建线程池

目录 1、newCachedThreadPool 2、newFixedThreadPool(fixed:固定的) 3、newSingleThreadExecutor 4、newScheduledThreadPool 5、newSingleThreadScheduledExecutor 6、newWorkStealingPool 7、为什么不推荐使用内置线程池&#xff1f…