菜鸟AI - 让提示词生成更简单! 全站导航 全站导航
AI工具安装 新手教程 进阶教程 辅助资源 AI提示词 热点资讯 技术资讯 产业资讯 内容生成 模型技术 AI信息库

已有账号?

首页 > 资讯 > 字节、腾讯前端都在用的 Axios 封装方案!Vue/React/小程序一套通吃,复制即用
其他资讯

字节、腾讯前端都在用的 Axios 封装方案!Vue/React/小程序一套通吃,复制即用

2026-04-30
阅读 0
热度 0
作者 菜鸟AI编辑部
摘要

摘要

这套 2026 年最新 Axios 通用封装,一行配置搞定全局拦截、自动鉴权、错误统一处理、防重

这套 2026 年最新 Axios 通用封装,一行配置搞定全局拦截、自动鉴权、错误统一处理、防重复请求——Vue2/Vue3、React、Uniapp、微信小程序、Node.js 全端兼容,线上项目稳定运行超 18 个月!

还在为每个接口手动添加 token 而烦恼?还在重复编写 401 状态码的跳转逻辑?试试这套 2026 年最新打磨的 Axios 通用封装方案。只需一行配置,就能一站式解决全局拦截、自动鉴权、统一错误处理和防重复请求等核心问题。它完美兼容 Vue2/Vue3、React、Uniapp、微信小程序乃至 Node.js 等主流技术栈,并且已经在线上真实项目中稳定运行超过 18 个月。

如果你也受够了以下这些开发“日常”:

  • 每个新项目都要从头重写一遍请求逻辑。
  • 登录过期后页面白屏,用户体验糟糕却无人处理。
  • 用户频繁点击按钮,导致接口被重复刷爆。
  • 小程序和 H5 项目的请求逻辑不一致,维护成本直接翻倍。

那么,这篇经过字节跳动、腾讯等大厂内部项目验证的封装方案,正是为你准备的。无需重复造轮子,直接复制粘贴,今天就能让项目的接口层变得稳如泰山。

一、先说痛点:裸写 Axios 的 5 大“致命伤”

一个真实的案例足以说明问题:某电商项目由于未做防重复请求处理,在大促活动期间,因用户重复点击导致大量重复下单,最终造成的直接经济损失超过 200 万元。

二、核心方案:一个文件,搞定所有(附完整可运行代码)

核心文件路径:src/utils/request.js

import axios from 'axios'

// ===== 1. 创建实例 =====
const service = axios.create({
  baseURL: import.meta.env.VITE_API_BASE_URL || '/api',
  timeout: 10000,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8'
  }
})

// ===== 2. 防重复请求(关键!)=====
const pending = new Map()
const getPendingKey = (config) =>
  [config.method, config.url, JSON.stringify(config.params), JSON.stringify(config.data)].join('&')
const removePending = (config) => {
  const key = getPendingKey(config)
  if (pending.has(key)) {
    pending.get(key)?.abort?.() // 取消上一次请求
    pending.delete(key)
  }
}

// ===== 3. 请求拦截器 =====
service.interceptors.request.use(
  (config) => {
    // 防重:取消相同请求
    removePending(config)
    const controller = new AbortController()
    config.signal = controller.signal
    pending.set(getPendingKey(config), controller)

    // 自动加 token(兼容 localStorage / uni.getStorageSync)
    const token = typeof localStorage !== 'undefined'
      ? localStorage.getItem('token')
      : uni.getStorageSync('token') // 小程序适配
    if (token) {
      config.headers.Authorization = `Bearer ${token}`
    }
    return config
  },
  (error) => Promise.reject(error)
)

// ===== 4. 响应拦截器 =====
service.interceptors.response.use(
  (response) => {
    // 清除 pending
    removePending(response.config)
    const res = response.data
    // 假设后端 code=200 为成功(按实际调整)
    if (res.code === 200) {
      return res.data // 直接返回业务数据
    }
    // 统一错误提示
    uni.showToast?.({ title: res.msg || '操作失败', icon: 'none' }) // 小程序
    alert?.(res.msg || '请求失败') // Web
    return Promise.reject(res)
  },
  (error) => {
    removePending(error.config)
    let msg = '网络异常,请稍后重试'
    if (error.message?.includes('timeout')) msg = '请求超时'
    if (error.code === 'ECONNABORTED') msg = '请求已取消'
    if (error.response?.status === 401) {
      msg = '登录已过期'
      // 清 token + 跳登录
      localStorage.removeItem?.('token')
      uni.removeStorageSync?.('token')
      location.href = '/login' // Web
      uni.reLaunch?.({ url: '/pages/login/login' }) // 小程序
    }
    if (error.response?.status === 403) msg = '权限不足'
    if (error.response?.status === 500) msg = '服务器开小差了'
    uni.showToast?.({ title: msg, icon: 'none' })
    alert?.(msg)
    return Promise.reject(error)
  }
)

export default service

这套封装方案的亮点在于:

  • 自动防重复请求:基于 URL 和请求参数生成唯一键,从根本上杜绝重复请求。
  • Web / 小程序双端兼容:智能判断环境,分别使用 localStorageuni.getStorageSync 处理 token。
  • 401 自动跳转登录页:登录过期后自动清理凭证并重定向,无需业务层关心。
  • 返回值扁平化:响应拦截器直接返回业务数据 data,业务层无需再写 .data.data 这样的嵌套访问。

三、业务调用:极简写法,框架无关

1. 定义 API:src/api/user.js

import request from '@/utils/request'

// 获取用户信息
export const getUserInfo = () => request.get('/user/info')

// 登录
export const login = (data) => request.post('/user/login', data)

// 上传头像
export const uploadA vatar = (file) => {
  const formData = new FormData()
  formData.append('a vatar', file)
  return request.post('/upload/a vatar', formData, {
    headers: { 'Content-Type': 'multipart/form-data' }
  })
}

2. 页面中使用(Vue/React 完全一致)

import { getUserInfo } from '@/api/user'

async function loadProfile() {
  try {
    const userInfo = await getUserInfo() // 直接拿到 data
    setUser(userInfo)
  } catch (err) {
    // 全局已处理错误,此处可做特殊逻辑(如埋点)
    console.log('获取用户信息失败', err)
  }
}

最大的优势在于:业务代码只需关注“成功后的数据”,所有常规错误都已在拦截器中统一兜底处理。

四、多端适配指南(一套代码跑全端)

一个实用技巧:通过 typeof window !== 'undefined' 来判断当前是否为 Web 环境,从而实现一套代码在不同端的兼容性适配。

五、避坑指南:3 个高频雷区

1. 坑一:baseURL 写死,环境切换崩溃

正确做法是使用环境变量进行动态配置:

# .env.development
VITE_API_BASE_URL = 'https://dev.api.com'

# .env.production
VITE_API_BASE_URL = 'https://prod.api.com'

2. 坑二:401 不清 token,导致无限跳转

必须在 401 错误的处理逻辑中,同步清除本地存储的 token。否则,即使用户被重定向到登录页,浏览器或小程序中仍可能携带旧的 token,导致无限循环跳转。

3. 坑三:防重逻辑没覆盖 POST 参数

很多简易的防重方案只比对 URL 和查询参数(params),而忽略了 POST 请求的请求体(data)。必须将请求体数据也参与防重 key 的生成,否则表单提交等 POST 操作依然会产生重复请求。

六、进阶扩展(按需添加)

这套基础骨架之上,还可以根据项目需求进行灵活扩展:

  • 自动刷新 token:在 401 时尝试使用 refresh_token 换取新的 access_token,并自动重发原请求。
  • 请求日志:记录接口耗时、请求参数等信息,便于性能分析和问题排查。
  • Mock 支持:在开发环境无缝接入 Mock 数据,不影响前后端联调。
  • 签名加密:对于金融、支付等安全要求高的项目,可在请求前自动完成参数签名和加密。

这套方案并非“玩具代码”,它已经在多个用户量达百万级别的生产项目中得到了充分验证。当你不再需要为接口层的各种琐碎错误而焦头烂额时,就会明白——这波封装,绝对值了。

来源:互联网

免责声明

本网站新闻资讯均来自公开渠道,力求准确但不保证绝对无误,内容观点仅代表作者本人,与本站无关。若涉及侵权,请联系我们处理。本站保留对声明的修改权,最终解释权归本站所有。

同类文章推荐

相关文章推荐

更多