Jansiel Notes

Axios:请求响应拦截器

如果每次发送网络请求都要手动携带上token,这无疑是加剧了工作量。借助工程化中模块化的思想,如果我设置个统一处理网络请求的模块,就可以完美解决这个问题。于是,axiso中的请求响应拦截器由此而生。


为什么要做拦截器

原因

  1. 统一处理请求和响应
    1. 请求 拦截器:可以在每个请求发送之前对请求进行处理。例如,可以在所有请求中添加认证 token,设置统一的 headers,或者进行参数校验。
    2. 响应 拦截器:可以在每个响应到达之前对响应进行处理。例如,可以统一处理错误,解析响应数据,或者重定向到登录页面。
  2. 错误处理
    1. 通过响应拦截器,可以统一捕获和处理错误。例如,可以在拦截器中检查响应状态码,如果是 401(未授权)状态码,可以自动刷新 token 或者跳转到登录页面。
  3. 方便数据转换
    1. 可以在请求发送之前或响应到达之后对数据进行转换。例如,可以在请求拦截器中将请求的数据转换为所需的格式,或者在响应拦截器中将响应的数据转换为更易于使用的格式。

之于工程化的意义

代码简洁和可维护性

  • 使用拦截器可以避免在每个请求或响应中重复编写相同的逻辑,提升代码的简洁性和可维护性。例如,统一的错误处理逻辑可以在拦截器中实现,而不是分散在每个请求中。

一致性

  • 拦截器可以确保所有请求和响应都经过相同的处理逻辑, 保证行为的一致性。例如,可以确保每个请求都携带认证信息,或每个错误都经过统一的处理。

灵活性和扩展性

  • 拦截器使得请求和响应的处理更加灵活和可扩展。例如,可以根据不同的业务需求动态添加或移除拦截器,实现不同的功能。

总结来说,Axios 的拦截器功能通过在请求和响应处理过程中提供统一的处理机制,使得代码更加简洁、可维护、一致,并提升了系统的灵活性和扩展性。这些都是现代前端工程化实践中的重要组成部分。

Jansiel_Essay_1718073764512


怎么使用(配置)拦截器

设置拦截器

我们在 src > utils 文件夹下 封装一个 request.js 文件

  1. 创建并自定义一个Axios实例
  • baseURL:定义了请求的基础 URL。所有通过这个实例发送的请求都会使用这个 URL 作为基准路径。
 1import axios from 'axios'
 2import { useUserStore } from '@/stores'
 3import router from '@/router'
 4import { ElMessage } from 'element-plus'
 5const baseURL = 'http://127.0.0.1:80'
 6
 7const instance = axios.create({
 8  baseURL,
 9  timeout: 10000
10})
11
  1. 配置请求 拦截器
  • instance.interceptors.request.use:为 Axios 实例添加一个请求拦截器。
  • (config) => { ... }:这是请求拦截器的成功处理函数,当请求发送之前会调用这个函数。
  • (err) => Promise.reject(err):这是请求拦截器的错误处理函数,如果请求配置阶段出错,会调用这个函数并返回一个被拒绝的 Promise。
 1instance.interceptors.request.use(
 2  (config) => {
 3    const useStore = useUserStore()  // 获取用户状态
 4    // 检查并添加token
 5    if (useStore.token) {
 6      config.headers.Authorization = useStore.token
 7    }
 8    return config // 返回配置
 9  },
10  (err) => Promise.reject(err)  // 错误处理
11)
12
  1. 配置响应 拦截器
  • if (res.data.code === 0):假设 API 返回的数据中包含 code 字段,表示业务状态码。 code0 表示业务成功。这里检查 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 路由器将用户重定向到登录页面。
 1instance.interceptors.response.use(
 2  // 成功响应处理函数
 3  (res) => {
 4    if (res.data.code === 0) {
 5      return res // 没问题就返回数据 res
 6    }
 7    // 否则就是有问题,返回以恶个被拒绝的 promise 状态。
 8    ElMessage.error(res.data.message || '服务异常')
 9    return Promise.reject(res.data)
10  },
11  (err) => {
12    if (err.response?.status === 401) {
13      router.push('/login')
14    }
15    ElMessage.error(err.response.data.message || '服务异常')
16    return Promise.reject(err)
17  }
18)
19

响应拦截器的思路就是:

  • 如果成功,就返回数据。
  • 如果失败就统一处理
  1. 导出模块
1export default instance
2

使用

假设现在有一个api模块,是用来处理网络请求的。

  1. 封装接口

在src > api 模块新建一个 handleData.js

1import request from '@/utils/request'  // 导入模块
2
3// 导出具体处理请求
4export const handleDate = ( data ) => request.post('/handledata', data)
5
  1. 使用接口

假设在 index.vue 中使用

涉及网络请求,所以异步处理。

1import { handleData } from '@/api/handleData.js'
2
3const myData = ref('Hello world, I am mCell.')
4
5const postData = async () => {
6  await handleData(myData.value)
7}
8postData()
9