axios 封装

Fetch API

选择或者不选择它?
        Fetch是AJAX的替换方案,基于Promise设计,很好的进行了关注分离,有很大一批人喜欢使用fetch进行项目开发;
        但是Fetch的缺点也很明显,首先需要明确的是Fetch是一个 low-level(底层)的API,没有帮助你封装好各种各样的功能和实现;
        比如发送网络请求需要自己来配置Header的Content-Type,不会默认携带cookie等;
        比如错误处理相对麻烦(只有网络错误才会reject,HTTP状态码404或者500不会被标记为reject);
        比如不支持取消一个请求,不能查看一个请求的进度等等;
        MDN Fetch学习地址:https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch

const data = { username: "example" };

fetch("https://example.com/profile", {
  method: "POST", // or 'PUT'
  headers: {
    "Content-Type": "application/json",
  },
  body: JSON.stringify(data),
})
  .then((response) => response.json())   // 把响应体里的 JSON 字符串解析成 JS 对象
  .then((data) => {
    console.log("Success:", data);
  })
  .catch((error) => {
    console.error("Error:", error);
  });

axios

        axios是目前前端使用非常广泛的网络请求库
主要特点包括:
        在浏览器中发送 XMLHttpRequests 请求;
        在 node.js 中发送 http请求;
        支持 Promise API;
        拦截请求和响应;
        转换请求和响应数据;

function getList(){
    axios.request({
        url:'/article/home/index',
        method:'get',
        baseURL:'http://test.mediastack.cn/'

    }).then(
        res => {
        console.log("get res:",res);
    },error => {
        console.log("get request failed:",error);  
    }
    );
}

axios响应拦截器和请求拦截器

拦截器的代码建议单独封装成一个请求工具模块

✅ 这样封装的好处:

  • 只在一处配置,全局生效,避免重复逻辑。

  • 清晰职责:api/request.js 专门管理网络请求。

  • 项目更模块化、维护更简单。

// src/api/request.js
import axios from 'axios';

// 创建实例
const service = axios.create({
  baseURL: 'http://localhost:8888', // 或写环境变量
  timeout: 10000,
});

// 请求拦截器
service.interceptors.request.use(
  (config) => {
    // 请求前的处理逻辑 

    // 设置请求头格式 
    config.headers["Content-Type"] = "application/json"; 

    // 添加 Token(身份验证)  
    try {
      const token = localStorage.getItem('token');
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
    } catch (e) {
      console.warn('获取 token 失败', e);
    }

    return config;
  },
  (error) => Promise.reject(error)  // 请求出错,比如网络断开、拦截器代码异常
);


// 响应拦截器
service.interceptors.response.use(
  (response) => {
    // 业务逻辑错误处理(可以根据后端返回的 code 来判断)
    const res = response.data;
    if (res.code !== 0) {
      console.error('接口报错:', res.message || '未知错误');
      return Promise.reject(new Error(res.message || 'Error'));
    }

    // 成功响应直接返回数据
    return res;
  },
  (error) => {
    // 响应错误处理
    if (error.response) {
      // HTTP 状态码错误处理(例如:401 未授权)
      switch (error.response.status) {
        case 401:
          alert('登录已过期,请重新登录');
          window.location.href = '/login'; // 重定向到登录页
          break;
        case 500:
          alert('服务器出错,请稍后再试');
          break;
        default:
          alert('请求出错,请稍后重试');
          break;
      }
    } else {
      console.error('请求错误:', error);
    }

    // 将错误信息返回给调用者
    return Promise.reject(error);
  }
);

export default service;

 ✅ 使用方式(在具体接口文件中)

// src/api/bill.js
import request from './request';

export const getBillListApi = () => request.get('/list');
export const addBillApi = (data) => request.post('/list', data);

 🔁 如果使用 redux + createAsyncThunk

// redux 中的异步函数
export const fetchBillList = createAsyncThunk(
  'bill/fetch',
  async () => {
    const res = await request.get('/list');
    return res.data;
  }
);

示例:

推荐目录结构与命名方式:

/src
  ├── /services         // ✅ 所有接口请求相关的 API 模块
  │    ├── index.js     // 汇总导出所有模块 API
  │    ├── user.js      // 用户相关接口
  │    ├── auth.js      // 权限/登录相关接口
  │    ├── menu.js      // 菜单相关接口
  │    └── ...更多模块
  │
  ├── /utils
  │    └── http.js      // ✅ axios 实例 + 请求拦截/响应拦截统一封装

✅ 示例一:utils/http.js(封装 axios 实例)

// utils/http.js
import axios from "axios";
import { getSession } from "next-auth/react";

const http = axios.create({
  baseURL:
    process.env.NODE_ENV === "development"
      ? "http://localhost:3000/proxy"
      : "https://api.jsonlee.cn",
  timeout: 10000,
  headers: {
    "Content-Type": "application/json",
  },
});

http.interceptors.request.use(
  async (config) => {
    const token = localStorage.getItem('token');
      if (token) {
        config.headers.Authorization = `Bearer ${token}`;
      }
    return config;
  },
  (error) => Promise.reject(error)
);

http.interceptors.response.use(
  (response) => {
    const res = response.data;
    if (res.code !== 0) {
      return Promise.reject(res.message || "接口请求失败");
    }
    return res;
  },
  (error) => Promise.reject(error)
);

export default http;

 ✅ 示例二:services/menu.js(菜单模块接口)

// services/menu.js
import http from "@/utils/http";

export const getMenuAuthority = (authorityId) =>
  http.post("/menu/getMenuAuthority", { authorityId });

export const getAllMenus = () => http.get("/menu/getAllMenus");

✅ 示例三:services/index.js(统一导出接口) 

// services/index.js

export { getMenuAuthority, getAllMenus } from "./menu"; // 只导出部分 menu 模块 API
export * from "./auth"; // 导出 auth 模块所有导出
export * from "./user"; // 导出 user 模块所有导出

组件里调用:

import { getMenuAuthority } from "@/services";

### 如何封装 Axios 以简化 HTTP 请求并增强功能 #### 封装的意义 通过封装 Axios,开发者能够在 Vue 或其他前端框架中统一处理 HTTP 请求,从而提升代码的可维护性和可扩展性。这种封装方式允许配置统一的请求头、拦截器以及错误处理逻辑,减少冗余代码的同时也提高了开发效率[^1]。 --- #### 封装的具体实现步骤 ##### 1. 安装 Axios 在项目中引入 Axios 是第一步操作。可以通过 npm 或 yarn 进行安装: ```bash npm install axios ``` 或者使用 Yarn: ```bash yarn add axios ``` --- ##### 2. 创建 Axios 实例 为了便于管理和定制化需求,通常会创建一个独立的 Axios 实例,并在此基础上进行进一步封装。 ```javascript // src/utils/request.js import axios from 'axios'; const service = axios.create({ baseURL: process.env.VUE_APP_BASE_API, // 设置基础 URL 地址 timeout: 5000, // 超时时间 (毫秒) headers: { // 默认请求头 'Content-Type': 'application/json', }, }); export default service; ``` 此部分实现了基本的 Axios 配置,包括 `baseURL` 和超时设置等参数[^3]。 --- ##### 3. 添加请求拦截器 请求拦截器用于在发送请求前对数据或配置进行预处理,例如添加 Token 认证信息或其他公共字段。 ```javascript service.interceptors.request.use( config => { const token = localStorage.getItem('token'); // 假设 Token 存储于本地存储 if (token) { config.headers['Authorization'] = `Bearer ${token}`; // 自动携带认证信息 } return config; }, error => { console.error(error); // 打印错误日志 Promise.reject(error); } ); ``` 这段代码展示了如何动态注入 Token 到请求头部,同时提供了错误捕获机制。 --- ##### 4. 添加响应拦截器 响应拦截器负责对接收到的数据进行初步解析和异常处理,确保返回给业务层的是干净的结果。 ```javascript service.interceptors.response.use( response => { const res = response.data; if (res.code && res.code !== 200) { // 如果服务端返回的状态码不正常,则抛出错误 Message.error(res.message || 'Error'); return Promise.reject(new Error(res.message || 'Request failed')); } else { return res; // 返回成功后的数据体 } }, error => { if (error.response) { switch (error.response.status) { case 401: MessageBox.confirm('登录状态已过期,请重新登录', '提示', { confirmButtonText: '确认', cancelButtonText: '取消', type: 'warning' }).then(() => { window.location.href = '/login'; // 跳转到登录页 }); break; case 403: Message.error('权限不足'); break; case 404: Message.error('资源未找到'); break; default: Message.error(`服务器内部错误(${error.response.status})`); } } else { Message.error('网络连接失败'); } return Promise.reject(error); } ); ``` 这里不仅完成了常规的成功/失败判断,还针对不同类型的 HTTP 错误进行了个性化提示。 --- ##### 5. 封装通用请求方法 为了让调用更加直观简单,可以提供一些便捷的方法来发起 GET、POST 等常见请求类型。 ```javascript export function get(url, params = {}) { return service.get(url, { params }); } export function post(url, data = {}, options = {}) { return service.post(url, data, options); } ``` 这些函数隐藏了底层细节,使得组件中的实际调用变得非常简洁明了[^2]。 --- ##### 6. 使用封装好的 Axios 实例 最后,在任何需要的地方都可以轻松导入并利用这个经过优化过的工具库完成各种 API 的交互工作。 ```javascript import { get, post } from '@/utils/request'; get('/api/user/info').then(response => { console.log('User Info:', response); }); post('/api/login', { username: 'admin', password: 'password' }) .then(response => { console.log('Login Success:', response); }) .catch(err => { console.error('Login Failed:', err); }); ``` 以上例子说明了如何快速集成封装Axios 来执行具体的接口访问任务。 --- #### 总结 通过对 Axios 的全面封装,不仅可以显著降低重复劳动量,还能有效改善项目的整体架构质量。无论是简单的 CRUD 操作还是复杂的跨域通信场景,都能从中受益匪浅[^1]。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值