使用 axios 拦截器实现请求和响应的统一处理(附常见面试题)

在现代前端开发中,我们经常需要向服务器发送 HTTP 请求,并根据响应内容做不同的处理。axios 是一个流行的 HTTP 库,提供了 拦截器 功能,可以在请求和响应阶段插入自定义逻辑,这使得我们在处理认证、错误提示等场景时更为简洁、统一。

本文将讲解如何利用 axios 的请求拦截器和响应拦截器来处理 token、重定向、错误提示等场景,并附上一些常见的面试问题。

一、代码实现

首先,我们来看一个使用 axios 的拦截器实例代码:

javascript 复制代码
import axios, { type AxiosResponse } from 'axios'
import router from '@/router'
import { ElMessage } from 'element-plus'
import { ResultEnum } from '@/enums/ResultEnum'
import { TOKEN_KEY } from '@/enums/SystemEnum'

// 创建 axios 实例
const AXIOS = axios.create({
  baseURL: '/lili-api',
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  }
})

// 请求拦截器
AXIOS.interceptors.request.use(
  (config) => {
    // 从 localStorage 中获取 token
    const token = localStorage.getItem(TOKEN_KEY)
    
    if (token) {
      // 确保 headers 存在
      config.headers = config.headers || {}
      config.headers.Authorization = `Bearer ${token}`  // 使用标准的 Bearer 认证方式
    }
    return config
  },
  (error) => {
    console.error("请求错误:", error)
    return Promise.reject(error)
  }
)

// 响应拦截器
AXIOS.interceptors.response.use(
  (response) => {
    const { code, message } = response.data

    switch (code) {
      case ResultEnum.NO_AUTH:
        // 无权限,清除 token 并重定向
        localStorage.removeItem(TOKEN_KEY)
        router.push('/login')
        break
      case ResultEnum.LOGIN_FAIL:
        // 登录失败,显示消息并清除 token
        ElMessage.error(message || "登录失败")
        localStorage.removeItem(TOKEN_KEY)
        break
      case ResultEnum.SUCCESS:
        // 成功响应,直接返回 data
        return response.data as AxiosResponse<HttpResponse>
      default:
        // 其他错误状态,显示错误消息
        if (message) {
          ElMessage.error(message)
        }
        break
    }
    
    return response.data
  },
  (error) => {
    // 响应错误的处理
    if (error.response) {
      ElMessage.error(`请求错误:${error.response.status}`)
    } else {
      ElMessage.error("网络错误,请检查您的网络连接")
    }
    console.error("响应错误:", error)
    return Promise.reject(error)
  }
)

export default AXIOS

二、代码详解

让我们一步步分析这个代码实现。

1. 创建 axios 实例
javascript 复制代码
const AXIOS = axios.create({
  baseURL: '/lili-api',
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  }
})

这里用 axios.create() 创建了一个 axios 实例 AXIOS。这样做的好处是可以给该实例绑定一个特定的基础 URL (baseURL),以后所有用 AXIOS 发送的请求都会自动加上这个 URL 前缀,省去了我们在每个请求里手动写基础路径的麻烦。

2. 请求拦截器
javascript 复制代码
AXIOS.interceptors.request.use(
  (config) => {
    const token = localStorage.getItem(TOKEN_KEY)
    
    if (token) {
      config.headers = config.headers || {}
      config.headers.Authorization = `Bearer ${token}`  // 使用标准的 Bearer 认证方式
    }
    return config
  },
  (error) => {
    console.error("请求错误:", error)
    return Promise.reject(error)
  }
)

请求拦截器会在每个请求发送前执行,它主要用来:

  • 检查 localStorage 是否有 token。如果有,将其添加到请求头的 Authorization 字段,以 Bearer 格式添加,更符合 RESTful API 认证标准。
  • 添加 Content-Typeapplication/json;charset=utf-8,表示请求体的数据格式是 JSON。
  • 使用 console.error 方便调试,输出请求拦截阶段的错误。
3. 响应拦截器
javascript 复制代码
AXIOS.interceptors.response.use(
  (response) => {
    const { code, message } = response.data

    switch (code) {
      case ResultEnum.NO_AUTH:
        localStorage.removeItem(TOKEN_KEY)
        router.push('/login')
        break
      case ResultEnum.LOGIN_FAIL:
        ElMessage.error(message || "登录失败")
        localStorage.removeItem(TOKEN_KEY)
        break
      case ResultEnum.SUCCESS:
        return response.data as AxiosResponse<HttpResponse>
      default:
        if (message) {
          ElMessage.error(message)
        }
        break
    }
    
    return response.data
  },
  (error) => {
    if (error.response) {
      ElMessage.error(`请求错误:${error.response.status}`)
    } else {
      ElMessage.error("网络错误,请检查您的网络连接")
    }
    console.error("响应错误:", error)
    return Promise.reject(error)
  }
)

响应拦截器主要功能是根据响应的状态码做出不同处理:

  • ResultEnum.NO_AUTH :无权限状态,清除 token,并重定向到登录页。
  • ResultEnum.LOGIN_FAIL :登录失败状态,弹出错误提示,并清除 token
  • ResultEnum.SUCCESS:请求成功时,直接返回数据。
  • 其他错误 :在 switch 语句中处理其他未知状态码,弹出错误信息提示。

同时,为了更全面地处理错误情况,响应错误 error 的处理阶段会显示更详细的状态码错误信息,或者在网络错误时给予用户相应提示。


三、面试中的常见问题

下面总结一些面试中关于 axios 拦截器的常见问题及答案示例:

1. 拦截器的作用是什么?

回答示例:拦截器允许我们在请求发出前和响应返回后插入自定义逻辑。常见用途包括在请求前检查认证 token 并添加到请求头、在响应后根据状态码处理错误、自动重定向等。拦截器可以减少代码重复,使请求的处理更集中、统一。

2. 为什么使用 axios.create 而不是直接用 axios

回答示例axios.create 创建了一个独立的 axios 实例,可以在这个实例上设置独特的基础配置,比如 baseURL、超时时间等。这种方式更模块化,适用于不同的 API,有助于项目中不同请求模块的管理。

3. 为什么要在请求头中设置 Content-Type

回答示例Content-Type 告诉服务器请求体的数据格式。设置为 application/json,表示我们发送的数据是 JSON 格式,这样服务器就知道如何解析请求数据。这种设置在 RESTful API 中是很常见的。

4. 为什么在无权限和登录失败时清除 token

回答示例NO_AUTHLOGIN_FAIL 表示当前的 token 已失效(过期或被篡改)。为了安全性,我们在这种情况下会清除 token 并重定向到登录页,这样可以确保用户在下一次请求前先重新登录,获取新的 token

5. 响应拦截器返回 response.data as AxiosResponse<HttpResponse> 的作用是什么?

回答示例response.data as AxiosResponse<HttpResponse> 是为了确保响应数据符合 HttpResponse 类型,让代码获得类型提示和安全检查的好处。这对 TypeScript 项目尤为重要,可以及时发现类型不匹配的问题,提升代码的可靠性。

6. 如何在拦截器中实现全局的加载动画?

回答示例 :可以在请求拦截器和响应拦截器中控制加载动画的显示和隐藏。在请求拦截器里显示加载动画,在响应完成或失败时隐藏它。通过全局状态管理工具(如 Vuex)控制 loading 状态,可以实现全局的加载效果。

相关推荐
崔庆才丨静觅7 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60617 小时前
完成前端时间处理的另一块版图
前端·github·web components
掘了7 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅8 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅8 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
崔庆才丨静觅8 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端
Moment8 小时前
富文本编辑器在 AI 时代为什么这么受欢迎
前端·javascript·后端
崔庆才丨静觅9 小时前
刷屏全网的“nano-banana”API接入指南!0.1元/张量产高清创意图,开发者必藏
前端
剪刀石头布啊9 小时前
jwt介绍
前端
爱敲代码的小鱼9 小时前
AJAX(异步交互的技术来实现从服务端中获取数据):
前端·javascript·ajax