如何打造优雅、高效的前端axios请求

  1. 包安装
shell 复制代码
npm install axios
  1. 创建 Axios 实例

在项目 src 目录下创建 api 文件夹,并在其中创建 axios.ts 文件:

ts 复制代码
import axios, { AxiosRequestConfig, AxiosResponse, AxiosInstance, AxiosPromise } from 'axios';  
import { ElNotification } from 'element-plus';  
  
// 创建 Axios 实例  
const instance: AxiosInstance = axios.create({  
  baseURL: import.meta.env.VITE_APP_BASE_API, // 基础路径  
  timeout: 10000, // 超时时间  
});  
  
// 请求拦截器  
instance.interceptors.request.use(  
  (config: AxiosRequestConfig) => {  
    // 请求拦截逻辑,如根据 env 设置不同环境的 token 等  
    return config;  
  },  
  (error) => Promise.reject(error)  
);  
  
// 响应拦截器  
instance.interceptors.response.use(  
  (response: AxiosResponse) => {  
    // 成功时处理逻辑  
    const { code, data, msg } = response.data;  
    if (code === 200) {  
      return Promise.resolve(data);  
    } else if (code === 401) {  
      ElNotification({ type: 'error', message: '登录过期,请重新登录' });  
      return Promise.reject(msg);  
    } else {  
      ElNotification({ type: 'error', message: msg });  
      return Promise.reject(msg);  
    }  
  },  
  (error: AxiosError) => {  
    // 错误时处理逻辑  
    let msg = '';  
    const status = error.response?.status;  
    switch (status) {  
      case 401:  
        msg = '登录过期,请重新登录';  
        break;  
      case 403:  
        msg = '拒绝访问';  
        break;  
      case 404:  
        msg = `请求地址出错: ${error.response?.config?.url}`;  
        break;  
      case 500:  
        msg = '服务器内部错误';  
        break;  
      case 502:  
        msg = '网关错误';  
        break;  
      case 503:  
        msg = '服务不可用';  
        break;  
      case 504:  
        msg = '网关超时';  
        break;  
      default:  
        msg = error.message;  
    }  
    ElNotification({ type: 'error', message: msg });  
    return Promise.reject(error);  
  }  
);  
  
// 请求方法  
instance.all = axios.all;  
instance.spread = axios.spread;  
instance.Axios = axios.Axios;  
  
export default instance;

3. 接口地址封装

src/api 目录下创建 api.ts 文件,对接口地址进行封装:

ts 复制代码
// 示例接口配置  
const api = {  
  users: {  
    get: () => `/api/v1/users`,  
    post: () => `/api/v1/user`,  
    put: (id: string) => `/api/v1/user/${id}`,  
    delete: (id: string) => `/api/v1/user/${id}`,  
    getDetail: (id: string) => `/api/v1/user/${id}`,  
  },  
};  
  
export default api;

4. 封装请求方法

src/api 下创建 apiInterceptor.ts 文件,封装请求和响应处理:

ts 复制代码
import instance from './axios';  
import api from './api';  
  
interface AxiosRequestFn<T> {  
  (options?: any): AxiosPromise<T>;  
}  
  
export const get = <T>(url: string, params?: any): AxiosPromise<T> => {  
  return instance.get<T>(url, { params });  
};  
  
export const post = <T>(url: string, data?: any): AxiosPromise<T> => {  
  return instance.post<T>(url, data);  
};  
  
export const put = <T>(url: string, data?: any): AxiosPromise<T> => {  
  return instance.put<T>(url, data);  
};  
  
export const del = <T>(url: string, data?: any): AxiosPromise<T> => {  
  return instance.delete<T>(url, { data });  
};  
  
export function getUsers<T>(page = 1, pageSize = 10): AxiosPromise<T> {  
  return get<T>(api.users.get(), { page, pageSize });  
}  
  
export function addUser<T>(data: any): AxiosPromise<T> {  
  return post<T>(api.users.post(), data);  
}  
  
export function getUserDetail<T>(id: string): AxiosPromise<T> {  
  return get<T>(api.users.getDetail(id));  
}  
  
export function updateUser<T>(id: string, data: any): AxiosPromise<T> {  
  return put<T>(api.users.put(id), data);  
}  
  
export function deleteUser<T>(id: string, data?: any): AxiosPromise<T> {  
  return del<T>(api.users.delete(id), data);  
}

5. 在组件中使用

在 Vue 组件中调用封装后的请求方法:

ts 复制代码
<template>
  <div>
    <el-table :data="tableData" stripe style="width: 100%">
      <el-table-column prop="name" label="姓名" width="180" />
      <el-table-column prop="address" label="地址" />
    </el-table>
  </div>
</template>

<script setup lang="ts">
import { getUsers } from '@/api/apiInterceptor';

const tableData = ref([]);

// 获取用户列表
const getUserList = async () => {
  try {
    const res = await getUsers();
    tableData.value = res;
  } catch (err) {
    console.error('获取用户列表失败:', err);
  }
};

onMounted(() => {
  getUserList();
});
</script>
相关推荐
失散136 分钟前
分布式专题——23 Kafka日志索引详解
java·分布式·云原生·架构·kafka
龙茶清欢1 小时前
4、除了常见的 services(业务微服务)和 gateway(API 网关)模块外,还必须建立一系列支撑性、平台级、基础设施类模块
微服务·架构·gateway
pccai-vip3 小时前
系分论文《论微服务架构在电商平台重构项目中的应用》
微服务·重构·架构
wanhengidc6 小时前
云手机远程控制的作用
网络·游戏·智能手机·架构·云计算
gb42152876 小时前
DDD 与传统三层架构的详细对比
数据库·架构
荒诞英雄7 小时前
菠萝滞销,帮帮我们(多个APP实例间pinia混乱)
前端·架构
麦当_7 小时前
ReAct 模式在 Neovate 中的应用
前端·javascript·架构
王道长服务器 | 亚马逊云8 小时前
AWS Route 53 详解:不只是 DNS,还能做智能流量调度
服务器·网络·微服务·云原生·架构·云计算·aws
ZZHHWW9 小时前
高性能架构01 -- 开篇
后端·架构
国科安芯9 小时前
AS32S601ZIT2型MCU:基于RISC-V架构的抗辐照设计与试验评估
网络·单片机·嵌入式硬件·fpga开发·架构·硬件架构·risc-v