如果每次发送网络请求都要手动携带上token,这无疑是加剧了工作量。借助工程化中模块化的思想,如果我设置个统一处理网络请求的模块,就可以完美解决这个问题。于是,axiso中的请求响应拦截器由此而生。
为什么要做拦截器
原因
-
统一处理请求和响应
- 请求 拦截器:可以在每个请求发送之前对请求进行处理。例如,可以在所有请求中添加认证 token,设置统一的 headers,或者进行参数校验。
- 响应 拦截器:可以在每个响应到达之前对响应进行处理。例如,可以统一处理错误,解析响应数据,或者重定向到登录页面。
-
错误处理
- 通过响应拦截器,可以统一捕获和处理错误。例如,可以在拦截器中检查响应状态码,如果是 401(未授权)状态码,可以自动刷新 token 或者跳转到登录页面。
-
方便数据转换
- 可以在请求发送之前或响应到达之后对数据进行转换。例如,可以在请求拦截器中将请求的数据转换为所需的格式,或者在响应拦截器中将响应的数据转换为更易于使用的格式。
之于工程化的意义
代码简洁和可维护性:
- 使用拦截器可以避免在每个请求或响应中重复编写相同的逻辑,提升代码的简洁性和可维护性。例如,统一的错误处理逻辑可以在拦截器中实现,而不是分散在每个请求中。
一致性:
- 拦截器可以确保所有请求和响应都经过相同的处理逻辑,保证行为的一致性。例如,可以确保每个请求都携带认证信息,或每个错误都经过统一的处理。
灵活性和扩展性:
- 拦截器使得请求和响应的处理更加灵活和可扩展。例如,可以根据不同的业务需求动态添加或移除拦截器,实现不同的功能。
总结来说,Axios 的拦截器功能通过在请求和响应处理过程中提供统一的处理机制,使得代码更加简洁、可维护、一致,并提升了系统的灵活性和扩展性。这些都是现代前端工程化实践中的重要组成部分。
怎么使用(配置)拦截器
设置拦截器
我们在
src > utils
文件夹下 封装一个request.js
文件
- 创建并自定义一个Axios实例
baseURL
:定义了请求的基础 URL。所有通过这个实例发送的请求都会使用这个 URL 作为基准路径。
import axios from 'axios'
import { useUserStore } from '@/stores'
import router from '@/router'
import { ElMessage } from 'element-plus'
const baseURL = 'http://127.0.0.1:80'
const instance = axios.create({
baseURL,
timeout: 10000
})
- 配置请求 拦截器
instance.interceptors.request.use
:为 Axios 实例添加一个请求拦截器。(config) => { ... }
:这是请求拦截器的成功处理函数,当请求发送之前会调用这个函数。(err) => Promise.reject(err)
:这是请求拦截器的错误处理函数,如果请求配置阶段出错,会调用这个函数并返回一个被拒绝的 Promise。
instance.interceptors.request.use(
(config) => {
const useStore = useUserStore() // 获取用户状态
// 检查并添加token
if (useStore.token) {
config.headers.Authorization = useStore.token
}
return config // 返回配置
},
(err) => Promise.reject(err) // 错误处理
)
- 配置响应 拦截器
if (res.data.code === 0)
:假设 API 返回的数据中包含code
字段,表示业务状态码。code
为0
表示业务成功。这里检查res.data.code
是否为0
,如果是,则认为业务成功,直接返回响应数据。ElMessage.error(res.data.message || '服务异常')
:如果code
不为0
,则认为业务失败,使用 Element Plus 的消息提示组件显示错误信息。res.data.message
包含具体的错误信息,如果没有,则显示默认的 '服务异常'。return res
:业务成功时返回完整的响应对象res
。return Promise.reject(res.data)
:业务失败时返回一个被拒绝的 Promise,传递res.data
以便在后续链式调用中处理。if (err.response?.status === 401)
:检查响应的状态码是否为401
(未授权)。如果是,则跳转到登录页面。router.push('/login')
:使用 Vue 路由器将用户重定向到登录页面。
instance.interceptors.response.use(
// 成功响应处理函数
(res) => {
if (res.data.code === 0) {
return res // 没问题就返回数据 res
}
// 否则就是有问题,返回以恶个被拒绝的 promise 状态。
ElMessage.error(res.data.message || '服务异常')
return Promise.reject(res.data)
},
(err) => {
if (err.response?.status === 401) {
router.push('/login')
}
ElMessage.error(err.response.data.message || '服务异常')
return Promise.reject(err)
}
)
响应拦截器的思路就是:
- 如果成功,就返回数据。
- 如果失败就统一处理
- 导出模块
export default instance
使用
假设现在有一个api模块,是用来处理网络请求的。
- 封装接口
在src > api 模块新建一个
handleData.js
import request from '@/utils/request' // 导入模块
// 导出具体处理请求
export const handleDate = ( data ) => request.post('/handledata', data)
- 使用接口
假设在
index.vue
中使用
涉及网络请求,所以异步处理。
import { handleData } from '@/api/handleData.js'
const myData = ref('Hello world, I am mCell.')
const postData = async () => {
await handleData(myData.value)
}
postData()