一个项目有多个后端地址,每个后端地址的请求拦截器和响应拦截器都不一样,该怎么封装

在处理多后端地址且拦截器逻辑各不相同的项目时,核心在于实现​​配置隔离​ ​和​​逻辑解耦​​。通过创建多个独立的Axios实例,并为每个实例配置专属的拦截器和默认设置,是当前最受推荐的做法。 以下是一种稳健的封装方案,你可以根据项目规模进行调整。

💡 核心封装策略

1. 创建多个Axios实例

为每个后端服务创建独立的Axios实例,这是实现配置隔离的基础。

arduino 复制代码
// src/utils/request.js
import axios from 'axios';

// 创建主业务API实例
export const mainAPI = axios.create({
  baseURL: process.env.VUE_APP_MAIN_API, // 从环境变量读取
  timeout: 10000,
});

// 创建第三方服务API实例(例如企业资源计划系统)
export const erpAPI = axios.create({
  baseURL: process.env.VUE_APP_ERP_API,
  timeout: 15000, // 该服务响应较慢,设置更长超时时间
});

// 创建文件上传服务实例
export const uploadAPI = axios.create({
  baseURL: process.env.VUE_APP_UPLOAD_API,
  timeout: 30000, // 文件上传需要更长时间
  headers: { 'Content-Type': 'multipart/form-data' }, // 专属请求头
});

2. 为每个实例配置独立的拦截器

针对每个实例的特定需求,设置专属的请求和响应拦截器。

javascript 复制代码
// 主业务API拦截器
mainAPI.interceptors.request.use(
  (config) => {
    // 自动添加认证Token
    const token = localStorage.getItem('access_token');
    if (token) {
      config.headers.Authorization = `Bearer ${token}`;
    }
    return config;
  },
  (error) => Promise.reject(error)
);

mainAPI.interceptors.response.use(
  (response) => {
    // 统一处理主业务后端的数据返回格式
    if (response.data.code === 200) {
      return response.data;
    } else {
      // 处理业务逻辑错误
      alert(response.data.message);
      return Promise.reject(new Error(response.data.message));
    }
  },
  (error) => {
    // 统一处理HTTP错误状态码
    if (error.response?.status === 401) {
      alert('登录已过期,请重新登录');
      // 清除token并跳转到登录页
      localStorage.removeItem('access_token');
      window.location.href = '/login';
    }
    return Promise.reject(error);
  }
);

// 第三方服务拦截器(逻辑可能完全不同)
erpAPI.interceptors.request.use(
  (config) => {
    // 第三方服务可能使用不同的认证方式,例如API Key
    config.headers['API-Key'] = process.env.VUE_APP_ERP_API_KEY;
    return config;
  },
  (error) => Promise.reject(error)
);

erpAPI.interceptors.response.use(
  (response) => {
    // 第三方服务的响应结构可能不同,直接返回数据
    return response;
  },
  (error) => {
    // 对第三方服务的错误有特殊处理
    console.error('ERP接口调用失败:', error);
    return Promise.reject(error);
  }
);

3. 模块化封装与统一导出

将不同业务的API请求函数按模块分类,便于维护和管理。

javascript 复制代码
// src/api/main.js (主业务API模块)
import { mainAPI } from '@/utils/request';

export const userAPI = {
  login: (data) => mainAPI.post('/user/login', data),
  getProfile: () => mainAPI.get('/user/profile'),
  updateProfile: (data) => mainAPI.put('/user/profile', data),
};

export const orderAPI = {
  list: (params) => mainAPI.get('/orders', { params }),
  detail: (id) => mainAPI.get(`/orders/${id}`),
  create: (data) => mainAPI.post('/orders', data),
};
javascript 复制代码
// src/api/erp.js (ERP系统API模块)
import { erpAPI } from '@/utils/request';

export const erp = {
  getInventory: (params) => erpAPI.get('/inventory', { params }),
  updateStock: (data) => erpAPI.post('/stock/update', data),
};

4. 高级优化技巧

  • ​防止重复请求​:在拦截器中实现取消重复请求的逻辑。
  • ​环境差异化配置​:结合环境变量,为开发、测试、生产环境配置不同的基础地址。
  • 请求重试机制:为不稳定的服务添加有限的自动重试功能。

📝 实践示例

在实际组件中使用封装好的API:

javascript 复制代码
// 在Vue组件中使用
import { userAPI } from '@/api/main';
import { erp } from '@/api/erp';

export default {
  methods: {
    async handleLogin() {
      try {
        const result = await userAPI.login({ 
          username: 'admin', 
          password: 'password' 
        });
        // 处理登录结果
      } catch (error) {
        // 错误已由拦截器统一处理,这里可根据需要做UI层面的特殊处理
        this.$message.error('登录失败');
      }
    },
    
    async loadInventory() {
      try {
        const inventory = await erp.getInventory({ warehouse: 'default' });
        this.inventoryData = inventory;
      } catch (error) {
        // ERP接口错误处理
      }
    }
  }
}

💎 封装的价值

通过这种封装方式,你获得了:

  • ​高度隔离​:各后端服务配置互不干扰。
  • ​维护性强​:相关变更影响范围小,易于调试和迭代。
  • ​开发体验好​:业务代码简洁明了,只需关注业务逻辑。
  • ​灵活性高​:轻松应对各后端服务的个性化需求。

这种多实例方案虽然初始设置稍显复杂,但随着项目发展,其优势会愈发明显,特别适合中大型前端项目。 希望这份详细的方案能帮助你更好地组织代码。如果你有更具体的场景或疑问,我可以提供更具针对性的建议。

相关推荐
潜心编码6 小时前
基于vue的停车场管理系统
前端·javascript·vue.js
三小河6 小时前
React Vite 中动态批量导入路由
前端·vue.js
拉不动的猪7 小时前
为什么不建议项目里用延时器作为规定时间内的业务操作
前端·javascript·vue.js
jason_yang7 小时前
vue3+element-plus按需自动导入-正确姿势
vue.js·vite·element
泉城老铁7 小时前
vue实现前端excel的导出
前端·vue.js
用户51681661458417 小时前
Lottie动画在前端web、vue、react中使用详解
前端·vue.js
咖啡の猫8 小时前
Vue收集表单数据
前端·javascript·vue.js
知识分享小能手8 小时前
uni-app 入门学习教程,从入门到精通, uni-app常用API的详细语法知识点(上)(5)
前端·javascript·vue.js·学习·微信小程序·小程序·uni-app
_志哥_8 小时前
多行文本超出,中间显示省略号的终极方法(适配多语言)
前端·javascript·vue.js