封装一个好用的axios,省时又省力,真香!!
loyalty
原创
category
前端
date_range
发表于2022-06-30
remove_red_eye
1077
source
0
favorite
0
tagapiaxios
简单聊一聊我在项目中是如何封装axios以及如何统一管理api接口,其主要目的是简化代码,使代码结构更清晰,便于后期更新维护。
一、初识 axios
axios
- 一个易用、简洁且高效的http库
它具有以下几个优点
- 支持
node
端和浏览器端 - 同样的API,node
和浏览器全支持,平台切换无压力 - 支持
Promise
- 使用Promise
管理异步,告别传统callback
方式 - 丰富的配置项 - 支持拦截器等高级配置
- 社区支持 -
axios
相关的npm
包数量一直在增长
优点还挺多,上手试试。
二、封装 axios
1. 安装依赖
可以使用npm、yarn等进行安装,这里我使用 yarn
。
yarn add axios
引入axios
。我一般是在src
下创建一个utils
文件夹,在其中新建一个request.js
放置封装好的axios
。
import axios from 'axios'
2. 创建实例
// 创建实例
const instance = axios.create()
// 创建实例后修改默认值
axios.defaults.baseURL = process.env.NODE_ENV == 'development' ? 'http://127.0.0.1:8081' : 'https://api.example.com' // 默认请求地址,需根据环境判断请求的路径
axios.defaults.timeout = 10000 // 超时时间,单位毫秒
axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded' // post请求头的设置
3. 请求拦截
/**
* 请求拦截器
* 每次请求前,如果存在token则在请求头中携带token
*/
axios.interceptors.request.use(
config => {
LoadingBar.start()
// 添加token
const token = getToken()
token && (config.headers.Authorization = "Bearer " + token)
return config
},
error => Promise.error(error)
)
4. 响应拦截
/**
* 响应拦截器
* 每次请求后,判断请求状态码是否正确,及数据做处理
*/
axios.interceptors.response.use(
/**
* 传输层:接口正常或异常,用http状态码
* 业务层:业务正常或异常,用自定义状态码
*/
// 请求成功
res => {
LoadingBar.stop()
// HTTP 状态码
if (res.status !== 200) {
return Promise.reject(res)
}
// 业务状态码
let code = res.data.code
if (!code || code === 2000) {
// 无code,则请求的是html页面;有code,则返回请求的数据
return Promise.resolve(res.data)
}
errorHandle(code, res.data.msg)
return Promise.reject(false)
},
// 请求失败
error => {
LoadingBar.stop()
const { response } = error
if (response) {
// 请求已发出,但是不在2xx的范围
errorHandle(response.status, response.data.message)
return Promise.reject(response)
} else {
tip('网络出现故障,请稍后再试')
}
}
)
5. 错误处理
/**
* 请求失败后的错误统一处理
* @param {Number} status 请求失败的状态码
*/
const errorHandle = (status, msg) => {
// 状态码判断
switch (status) {
// 2002: 用户名/密码错误
case 2002:
tip('用户名或密码错误!')
break
// 4003: token过期,清除token并跳转登录页
case 4003:
toLogin("登录信息过期")
break
// 其他状态码
...
default:
tip('后台维护中,请稍后再试')
}
}
/**
* 提示函数
*/
const tip = msg => {
// 使用UI框架自带的错误弹框即可
Vue.prototype.$msg.error(msg)
}
/**
* 跳转登录页
* 携带当前页面路由,以便在登录完成登录后返回当前页面
*/
const toLogin = async (msg) => {
// 移除token、用户信息
// 跳转登录页
router.replace({
path: '/login',
query: {
redirect: router.currentRoute.fullPath
}
})
}
三、使用 axios
1. 创建api接口
以user
模块为例,在src
目录下新建api
文件夹,用来存放项目的所有接口请求,新建user.js
,代码如下:
import axios from '@/utils/request'
/**
* @description: 用户登录
* @param {String} username 用户名
* @param {String} password 密码(aes加密)
*/
export const userLogin = params => {
return axios.post('/user/login', params)
}
// 其他user接口
...
2. 在页面使用
import { userLogin } from '@/api/user'
userLogin({
username: this.username,
password: this.password, // 记得加密QAQ
}).then(res => {
this.$msg.success('登录成功')
})
四、api 进阶
很多项目都是通过以上方式来调用接口的,但是这种方式有个弊端,在每个页面都得引入需要的API,如果某个界面用到不同模块的接口,得引入好几次,造成代码冗余。
在B站自学的时候,发现了一个更合适的方法,下面就来详细讲解一下。
1. 创建api接口
将user
模块作为一个整体导出。
import axios from '@/utils/request'
export const user = {
/**
* @description: 用户登录
* @param {String} username 用户名
* @param {String} password 密码(aes加密)
*/
userLogin(params) {
return axios.post('/user/login', params)
}
// 其他user接口
...
}
2. 创建index.js
在使用api时,经常需要import
或export
各种模块,那么有没有什么办法可以简化这种操作呢?答案是肯定的,下面就为大家介绍一下require.context
的基本使用方法:
require.context(directory,useSubdirectories,regExp),三个参数分别如下:
- directory 要查找的文件路径
- useSubdirectories 是否查找子目录
- regExp 要匹配文件的正则
具体使用方式见:webpack中require.context的作用
require.context
官网地址:webpack-requirecontext
本案例使用如下,将所有index.js
同级api导入,导入后统一导出,最后在main.js
将所有api挂载到vue
中
// 批量导出文件
const requireApi = require.context(
// api 目录的相对路径
'.',
// 是否查询子目录
false,
// 查询文件的一个后缀
/.js$/
)
let module = {}
requireApi.keys().forEach((key,index) => {
if(key === './index.js') return
Object.assign(module, requireApi(key))
})
export default module
3. 引入及使用
在main.js
引入所有api
import Vue from 'vue'
import api from '@/api'
Vue.prototype.$api = api
...
使用
this.$api.user.userLogin().then(res => {
// 接口响应成功后的一些处理...
})
五、总结
完结撒花😁😁😁
评论

暂无评论