基于 Axios 的 HTTP 请求封装文件解析

发布于:2025-08-12 ⋅ 阅读:(13) ⋅ 点赞:(0)
import axios from "axios";
import { ElMessage } from "element-plus";
import store from "@/store";
import router from "@/router";

// 创建axios实例
const service = axios.create({
  baseURL: "http://localhost:8080/api", // 后端地址
  timeout: 5000,
});

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    // 如果有token,添加到请求头
    if (store.getters.token) {
      config.headers["Authorization"] = "Bearer " + store.getters.token;
    }
    return config;
  },
  (error) => {
    console.log(error);
    return Promise.reject(error);
  }
);

// 响应拦截器
service.interceptors.response.use(
  (response) => {
    // 如果是blob类型的响应(文件下载),直接返回
    if (response.config.responseType === 'blob') {
      return response.data;
    }
    
    // 如果响应的Content-Type是text/csv,也直接返回
    const contentType = response.headers['content-type'];
    if (contentType && contentType.includes('text/csv')) {
      return response.data;
    }
    
    const res = response.data;

    // 如果code不是200,说明出错了
    if (res.code !== 200) {
      ElMessage({
        message: res.message || "请求失败",
        type: "error",
        duration: 5 * 1000,
      });

      // 401: 未登录
      if (res.code === 401) {
        store.dispatch("user/logout");
        router.push("/login");
      }

      return Promise.reject(new Error(res.message || "请求失败"));
    } else {
      return res;
    }
  },
  (error) => {
    console.log("err" + error);
    ElMessage({
      message: error.message,
      type: "error",
      duration: 5 * 1000,
    });
    return Promise.reject(error);
  }
);

export default service;

基于 Axios 的 HTTP 请求封装文件,提供了完整的请求/响应拦截、错误处理和认证机制。

1. 依赖导入

import axios from "axios";
import { ElMessage } from "element-plus";
import store from "@/store";
import router from "@/router";
  • axios:HTTP 请求库
  • ElMessage:ElementPlus 的消息提示组件
  • store:Vuex 状态管理器,用于获取用户 token
  • router:Vue Router,用于页面跳转(如登录失效时跳转到登录页)

2. 创建 Axios 实例

const service = axios.create({
  baseURL: "http://localhost:8080/api", // 后端地址
  timeout: 5000,
});
  • baseURL:设置基础 URL,所有请求都会以此为前缀
  • timeout:请求超时时间 5 秒,避免请求长时间挂起

3. 请求拦截器

service.interceptors.request.use(
  (config) => {
    // 如果有token,添加到请求头
    if (store.getters.token) {
      config.headers["Authorization"] = "Bearer " + store.getters.token;
    }
    return config;
  },
  (error) => {
    console.log(error);
    return Promise.reject(error);
  }
);

功能说明:

  • 自动添加认证头:检查 store 中是否有 token,如果有则自动添加到请求头
  • Bearer Token 格式:使用标准的 JWT Token 认证格式
  • 错误处理:捕获请求配置阶段的错误

4. 响应拦截器

这是代码的核心部分,处理各种响应情况:

4.1 特殊响应类型处理

// 如果是blob类型的响应(文件下载),直接返回
if (response.config.responseType === 'blob') {
  return response.data;
}

// 如果响应的Content-Type是text/csv,也直接返回
const contentType = response.headers['content-type'];
if (contentType && contentType.includes('text/csv')) {
  return response.data;
}
  • 文件下载处理:对于 blob 类型响应(通常是文件下载),直接返回数据
  • CSV 文件处理:对于 CSV 格式的响应,也直接返回原始数据
  • 避免数据结构解析:这些特殊类型不需要按照标准 API 响应格式处理

4.2 标准 API 响应处理

const res = response.data;
// 如果code不是200,说明出错了
if (res.code !== 200) {
  ElMessage({
    message: res.message || "请求失败",
    type: "error",
    duration: 5 * 1000,
  });
  // 401: 未登录
  if (res.code === 401) {
    store.dispatch("user/logout");
    router.push("/login");
  }
  return Promise.reject(new Error(res.message || "请求失败"));
} else {
  return res;
}

处理逻辑:

  1. 统一响应格式:假设后端返回格式为 { code: number, message: string, data: any }
  2. 错误状态处理:code 不为 200 时视为错误
  3. 用户提示:使用 ElMessage 显示错误信息
  4. 认证失效处理
    • 401 状态码表示未登录或 token 过期
    • 自动执行登出操作(清除 store 中的用户信息)
    • 跳转到登录页面
  5. 错误传播:返回 rejected Promise,便于上层捕获处理

4.3 网络错误处理

(error) => {
  console.log("err" + error);
  ElMessage({
    message: error.message,
    type: "error",
    duration: 5 * 1000,
  });
  return Promise.reject(error);
}
  • 网络异常:处理网络连接失败、超时等错误
  • 用户反馈:显示错误消息给用户
  • 错误日志:在控制台记录错误信息

5. 设计模式和最佳实践

5.1 拦截器模式

  • 请求拦截:统一添加认证信息
  • 响应拦截:统一处理错误和特殊情况

5.2 错误处理策略

  • 分层错误处理:网络错误、业务错误分别处理
  • 用户友好:所有错误都有用户提示
  • 自动化处理:认证失效自动跳转登录

5.3 代码复用

  • 全局配置:一次配置,整个项目复用
  • 统一格式:所有 HTTP 请求使用相同的处理逻辑

6. 使用示例

// 在组件中使用
import request from '@/utils/request'

// GET 请求
request.get('/users')

// POST 请求
request.post('/users', { name: 'John' })

// 文件下载
request.get('/export/csv', { responseType: 'blob' })

网站公告

今日签到

点亮在社区的每一天
去签到