当前位置: 首页 > article >正文

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

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

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

一、代码实现

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

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 实例
const AXIOS = axios.create({
  baseURL: '/lili-api',
  headers: {
    'Content-Type': 'application/json;charset=utf-8'
  }
})

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

2. 请求拦截器
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. 响应拦截器
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 状态,可以实现全局的加载效果。


http://www.kler.cn/a/385756.html

相关文章:

  • ElasticSearch学习笔记二:使用Java客户端
  • Go语言24小时极速学习教程(四)MySQL数据库的增删改查
  • Spring 中的 BeanDefinitionParserDelegate 和 NamespaceHandler
  • vue3中pinia状态管理库使用以及持久化配置方法总结
  • 【珠海科技学院主办,暨南大学协办 | IEEE出版 | EI检索稳定 】2024年健康大数据与智能医疗国际会议(ICHIH 2024)
  • Python作业05
  • OPPO开源Diffusion多语言适配器—— MultilingualSD3-adapter 和 ChineseFLUX.1-adapter
  • 【Android】ubutun 创建Androidstudio桌面快捷方式
  • 初始MQ(安装使用RabbitMQ,了解交换机)
  • HarmonyOs DevEco Studio小技巧28--部分鸿蒙生命周期详解
  • 陀螺仪原理探析
  • uni-app - - - - - 钉钉小程序 uni.showToast回调函数不执行问题(PC端钉钉小程序 接口API回调函数不执行)
  • 前端自动化测试selenium在最新探索使用
  • Chromium 中chrome.webRequest扩展接口定义c++
  • 稀土阻燃协效剂-氢氧化镁的应用
  • React核心概念与特点
  • python包管理工具pip和conda的使用对比
  • 如何编写有效的Prompt模板:提升大模型性能的关键
  • 数据结构---详解顺序表
  • python项目使用sqlalchemy的order_by方法报错‘Out of sort memory‘的解决方案
  • FP独立站引流革命:GG斗篷技术解锁流量新策略
  • Linux挖矿病毒(kswapd0进程使cpu爆满)
  • Linux环境基础开发工具的使用_yum源_vim_Git控制器
  • 【HGT】文献精讲:Heterogeneous Graph Transformer
  • 《XGBoost算法的原理推导》12-14决策树复杂度的正则化项 公式解析
  • 原创:使用Qt Creator作为Linux IDE,实现CMake编译和gdb单步调试