Axios:请求响应拦截器

288 阅读4分钟

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


为什么要做拦截器

原因

  1. 统一处理请求和响应

    1. 请求 拦截器:可以在每个请求发送之前对请求进行处理。例如,可以在所有请求中添加认证 token,设置统一的 headers,或者进行参数校验。
    2. 响应 拦截器:可以在每个响应到达之前对响应进行处理。例如,可以统一处理错误,解析响应数据,或者重定向到登录页面。
  2. 错误处理

    1. 通过响应拦截器,可以统一捕获和处理错误。例如,可以在拦截器中检查响应状态码,如果是 401(未授权)状态码,可以自动刷新 token 或者跳转到登录页面。
  3. 方便数据转换

    1. 可以在请求发送之前或响应到达之后对数据进行转换。例如,可以在请求拦截器中将请求的数据转换为所需的格式,或者在响应拦截器中将响应的数据转换为更易于使用的格式。

之于工程化的意义

代码简洁和可维护性

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

一致性

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

灵活性和扩展性

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

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


怎么使用(配置)拦截器

设置拦截器

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

  1. 创建并自定义一个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
})
  1. 配置请求 拦截器
  • 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)  // 错误处理
)
  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 路由器将用户重定向到登录页面。
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)
  }
)

响应拦截器的思路就是:

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

使用

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

  1. 封装接口

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

import request from '@/utils/request'  // 导入模块

// 导出具体处理请求
export const handleDate = ( data ) => request.post('/handledata', data)
  1. 使用接口

假设在index.vue中使用

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

import { handleData } from '@/api/handleData.js'

const myData = ref('Hello world, I am mCell.')

const postData = async () => {
  await handleData(myData.value)
}
postData()