惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

月光博客
月光博客
云风的 BLOG
云风的 BLOG
小众软件
小众软件
雷峰网
雷峰网
博客园 - 【当耐特】
V
V2EX
WordPress大学
WordPress大学
IT之家
IT之家
Last Week in AI
Last Week in AI
罗磊的独立博客
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Apple Machine Learning Research
Apple Machine Learning Research
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
V
Visual Studio Blog
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
有赞技术团队
有赞技术团队
The Cloudflare Blog
Jina AI
Jina AI
博客园 - 司徒正美
阮一峰的网络日志
阮一峰的网络日志
博客园 - 聂微东
大猫的无限游戏
大猫的无限游戏
博客园 - 三生石上(FineUI控件)
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com

膨胀自留地

使用CloudFlare标记管理功能优雅的使用谷歌分析 四天轻松版北京旅游攻略 Adsense税务居住地证明申请教程:如何申请中国税收居民身份证明以及Google Adsense更新新加坡税务信息教程 常见的 VPS 优化措施 HTML实现table表格移动端自动转为卡片样式 个人网站接入 Google 登录 如何从 GitHub 永久删除泄露的 .env 文件 Cloudflare设置www的域名跳转到不带www的域名 顶级iOS神器!全面解开App Store限制,AssPP Pro保姆级教程 BroadcastChannel将你的 Telegram Channel 转为微博客 Medama开源轻量级网站统计(分析)系统 白嫖一个网站监控面板:uptime-kuma 部署TraffMonetizer利用闲置VPS挂机赚钱 Counterscale-使用CloudflareWorkers部署的免费网站数据统计工具,界面类似umami 如何使用Cloudflare Email Routing创建域名邮箱免费发送邮件 使用Cron定时更新Hosts解决Gihub无法访问问题 容器化MariaDB/Mysql实现定时备份 JetBrains全家桶许可证服务器怎么找,JetBrains激活教程 图片加速接口:缓存图片,加速访问,解决防盗链 MySQL模糊查询再也不用like+%了,全文索引介绍及使用简介 为什么这么多人推荐你办理流量卡?流量卡怎么赚钱?怎么避坑? 借助Cloudflare Worker实现Google Analytics反代加速,规避广告屏蔽插件的拦截 etcd入门之在Centos上安装部署 Grafana在linux下安装和基本使用入门 Prometheus介绍、安装和基本功能快速入门 无需加速器,油猴插件解锁xbox云游戏 阿里云盘自动每日签到,无需部署,无需服务器 自定义VSCode终端主题样式 一行 CSS 代码实现响应式布局 – 使用 Grid 实现的响应式布局 加不加「/」?Nginx location 路径与 proxy_pass 的规律
封装一个最简单的Axios,避免过度封装!
2024-05-10 · via 膨胀自留地

#编程技术 2024-05-10 17:42:00 | 全文 2304 字,阅读约需 5 分钟 | 加载中... 次浏览

👋 相关阅读


axios 是目前最优秀的 HTTP 请求库之一,虽然 axios 已经封装的非常好了,我们可以直接拿过来用。但是在实际的项目中,我们可能还需要对 axios 在封装一下,以便我们更好的管理项目和各个借口。

但是,目前网上有特别多的针对于 axios 在项目中的封装。不得不说,很多大佬封装得非常全面,方方面面都考虑到了。但是我们的每个真的都需要那些封装吗?显然不是的,网上的很多封装其实都显得有点过度封装了!

本篇文章实现最简单 Axios 封装,让小伙伴们扩展起来容易一些。

1.封装目的

此次进行简单的封装,所以暂时没有考虑取消重复请求、重复发送请求、请求缓存等情况!这里主要实现以下目的:

  1. 实现请求拦截
  2. 实现响应拦截
  3. 常见错误信息处理
  4. 请求头设置
  5. api 集中式管理

2.初始化 axios 实例

虽然 axios 可以调用 get、post 等方法发起请求,但是我们为了更好的全局控制所有请求的相关配置,所以我们使用 axios.create() 创建实例的方法来进行相关配置,这也是封装 axios 的精髓所在。

示例代码:

// 创建 axios 请求实例
const serviceAxios = axios.create({
  baseURL: "", // 基础请求地址
  timeout: 10000, // 请求超时设置
  withCredentials: false, // 跨域请求是否需要携带 cookie
});

通过 create 方法我们得到了一个 axios 的实例,该实例上有很多方法,比如拦截器等等。我们创建实例的时候可以配置一些基础设置,比如基础请求地址,请求超时等等。

3.设置请求拦截

我们在发送请求的时候可能需要携带一些信息在请求头上,比如 token 等,所以说我们就需要将请求拦截下来,处理一些我们的业务逻辑。

示例代码:

// 创建请求拦截
serviceAxios.interceptors.request.use(
  (config) => {
    // 如果开启 token 认证
    if (serverConfig.useTokenAuthorization) {
      config.headers["Authorization"] = localStorage.getItem("token"); // 请求头携带 token
    }
    // 设置请求头
    if(!config.headers["content-type"]) { // 如果没有设置请求头
      if(config.method === 'post') {
        config.headers["content-type"] = "application/x-www-form-urlencoded"; // post 请求
        config.data = qs.stringify(config.data); // 序列化,比如表单数据
      } else {
        config.headers["content-type"] = "application/json"; // 默认类型
      }
    }
    console.log("请求配置", config);
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);

我们通过调用 axios 的实例方法来进行请求拦截。

4.设置响应拦截

axios 请求的返回结果里面包含了很多东西,我们的业务层面通常只需要后端返回的数据即可,所以我们需要设置相应拦截,在响应结果返回给业务层之前做一些操作。

示例代码:

// 创建响应拦截
serviceAxios.interceptors.response.use(
  (res) => {
    let data = res.data;
    // 处理自己的业务逻辑,比如判断 token 是否过期等等
    // 代码块
    return data;
  },
  (error) => {
    let message = "";
    if (error && error.response) {
      switch (error.response.status) {
        case 302:
          message = "接口重定向了!";
          break;
        case 400:
          message = "参数不正确!";
          break;
        case 401:
          message = "您未登录,或者登录已经超时,请先登录!";
          break;
        case 403:
          message = "您没有权限操作!";
          break;
        case 404:
          message = `请求地址出错: ${error.response.config.url}`;
          break;
        case 408:
          message = "请求超时!";
          break;
        case 409:
          message = "系统已存在相同数据!";
          break;
        case 500:
          message = "服务器内部错误!";
          break;
        case 501:
          message = "服务未实现!";
          break;
        case 502:
          message = "网关错误!";
          break;
        case 503:
          message = "服务不可用!";
          break;
        case 504:
          message = "服务暂时无法访问,请稍后再试!";
          break;
        case 505:
          message = "HTTP 版本不受支持!";
          break;
        default:
          message = "异常问题,请联系管理员!";
          break;
      }
    }
    return Promise.reject(message);
  }
);

5.完整示例

上面直接简单介绍了拦截等相关代码,接下来我们在实际项目中来演练一下,以 Vue 项目为例。

在 src 下面新建 http 文件夹,用来存储关于 axios 请求的一些文件,然后在 http 文件夹下新建 index.js 文件,用于封装我们的 axios,然后在新建 config 文件夹,主要用来创建配置文件,最后新建一个 api 文件夹,用于集中管理我们的接口。

文件夹目录如下:

图片alt

index.js 代码:

import axios from "axios";
import serverConfig from "./config";
import qs from "qs";
// 创建 axios 请求实例
const serviceAxios = axios.create({
  baseURL: serverConfig.baseURL, // 基础请求地址
  timeout: 10000, // 请求超时设置
  withCredentials: false, // 跨域请求是否需要携带 cookie
});
// 创建请求拦截
serviceAxios.interceptors.request.use(
  (config) => {
    // 如果开启 token 认证
    if (serverConfig.useTokenAuthorization) {
      config.headers["Authorization"] = localStorage.getItem("token"); // 请求头携带 token
    }
    // 设置请求头
    if(!config.headers["content-type"]) { // 如果没有设置请求头
      if(config.method === 'post') {
        config.headers["content-type"] = "application/x-www-form-urlencoded"; // post 请求
        config.data = qs.stringify(config.data); // 序列化,比如表单数据
      } else {
        config.headers["content-type"] = "application/json"; // 默认类型
      }
    }
    console.log("请求配置", config);
    return config;
  },
  (error) => {
    Promise.reject(error);
  }
);
// 创建响应拦截
serviceAxios.interceptors.response.use(
  (res) => {
    let data = res.data;
    // 处理自己的业务逻辑,比如判断 token 是否过期等等
    // 代码块
    return data;
  },
  (error) => {
    let message = "";
    if (error && error.response) {
      switch (error.response.status) {
        case 302:
          message = "接口重定向了!";
          break;
        case 400:
          message = "参数不正确!";
          break;
        case 401:
          message = "您未登录,或者登录已经超时,请先登录!";
          break;
        case 403:
          message = "您没有权限操作!";
          break;
        case 404:
          message = `请求地址出错: ${error.response.config.url}`;
          break;
        case 408:
          message = "请求超时!";
          break;
        case 409:
          message = "系统已存在相同数据!";
          break;
        case 500:
          message = "服务器内部错误!";
          break;
        case 501:
          message = "服务未实现!";
          break;
        case 502:
          message = "网关错误!";
          break;
        case 503:
          message = "服务不可用!";
          break;
        case 504:
          message = "服务暂时无法访问,请稍后再试!";
          break;
        case 505:
          message = "HTTP 版本不受支持!";
          break;
        default:
          message = "异常问题,请联系管理员!";
          break;
      }
    }
    return Promise.reject(message);
  }
);
export default serviceAxios;

config/index.js 代码:

const serverConfig = {
  baseURL: "https://smallpig.site", // 请求基础地址,可根据环境自定义
  useTokenAuthorization: true, // 是否开启 token 认证
};
export default serverConfig;
api/user.js 接口调用示例代码:
import serviceAxios from "../index";
export const getUserInfo = (params) => {
  return serviceAxios({
    url: "/api/website/queryMenuWebsite",
    method: "post",
    params,
  });
};
export const login = (data) => {
  return serviceAxios({
    url: "/api/user/login",
    method: "post",
    data,
  });
};

注意:get 请求需要传 params,post 请求需要传 data。

Vue 文件中调用示例:

import { login } from "@/http/api/user"
async loginAsync() {
      let params = {
        email: "123",
        password: "12321"
      };
      try {
        const response = await login(params);
        // 处理响应数据
        console.log(response.data);
      } catch (error) {
        // 处理错误情况
        console.error(error);
      }
    }

6.总结

我们这里只做了最最最基础的 axios 封装,但是可扩展性较高。相较于其它文章的过度封装,这里的封装形式其实可以满足大部分应用场景了。

我们在此基础上可以根据业务场景做一些以下扩展建议:

  • 请求拦截里面针对 token 进行处理
  • 响应拦截里面判断 token 是否过期等等
  • 在 config/index.js 里面动态更改 baseURL
  • 在请求拦截里面根据业务场景修改请求头
  • 在拦截里面设置全局请求进度条等等

VIA

不要过度封装!封装一个最简单的Axios!-阿里云开发者社区 https://developer.aliyun.com/article/975028


×