关于前端开发中常用的 axios 封装

前端、axios、网络请求
关于前端开发中常用的 axios 封装

jcLee95 的个人博客https://blog.csdn.net/qq_28550263?spm=1001.2101.3001.5343
邮箱 :[email protected]
本文地址https://blog.csdn.net/qq_28550263/article/details/131099244


相关文章:[《flutter 中的 dio 模块用法解析与二次封装》](https://blog.csdn.net/qq_28550263/article/details/131152631](https://blog.csdn.net/qq_28550263/article/details/131152631)


1. 概述

1.1 什么是 axios

Axios 是一个基于 Promise 的 HTTP 客户端,用于在浏览器和 Node.js 中发送异步请求。它是一个流行的 JavaScript 库,旨在简化客户端端与服务器端之间的数据传输过程。Axios 提供了一个简洁而强大的 API,可以轻松地执行各种 HTTP 请求,例如 GET、POST、PUT、DELETE 等。

Axios 具有以下特点和功能:

功能特点 描述
支持 Promise Axios 基于 Promise,可以利用 Promise 的优点,如链式调用、错误处理和异步操作。
跨浏览器支持 Axios 可在浏览器和 Node.js 环境中使用,提供了一致的 API。
自动转换数据 Axios 可以自动将请求和响应数据转换为不同的格式,如 JSON、XML、FormData 等。
拦截器 Axios 提供了请求和响应拦截器,可以在请求发送之前和响应返回之后进行拦截和处理。
取消请求 Axios 支持取消请求的功能,可以在需要时中止正在进行的请求。
错误处理 Axios 提供了全局的错误处理机制,可以方便地捕获和处理请求过程中的错误。
防止 CSRF Axios 可以通过设置请求头或者使用 CSRF 令牌来防止跨站请求伪造。

Axios 是一个功能强大、易于使用且广泛采用的 HTTP 客户端库,可以帮助开发者轻松地与服务器进行数据交互。无论是处理简单的 API 请求还是处理复杂的网络通信,Axios 提供了一套简洁而灵活的工具来满足各种需求。读者可以在以下博文阅览axios中文翻译文档:《axios 文档中文翻译》,地址:https://blog.csdn.net/qq_28550263/article/details/122537980

1.2 关于本文

2. 从 axios 的基本用法开始

2.1 axios 用法简介

2.1.1 安装和引入 axios 模块

npm install axios
# or
yarn add axios
# or
pnpm i axios

安装完成后你就可以如下引入axios:

import axios from 'axios';

2.1.2 发送GET请求

axios.get('/api/data')
  .then((response) => {
    
    
    // 处理成功响应
    console.log(response.data);
  })
  .catch((error) => {
    
    
    // 处理错误响应
    console.error(error);
  });

2.1.3 发送POST请求

axios.post('/api/data', {
    
     /* 数据 */ })
  .then((response) => {
    
    
    // 处理成功响应
    console.log(response.data);
  })
  .catch((error) => {
    
    
    // 处理错误响应
    console.error(error);
  });

2.2 为什么需要封装axios

尽管可以直接使用axios进行基本的请求,但未封装axios存在以下不便之处:

  1. 代码冗余:在每个请求中都需要重复编写请求配置、错误处理等逻辑,导致代码冗余和可读性降低。
  2. 配置不一致:如果项目中有多个地方使用axios,每个地方的配置可能不一致,导致代码风格不统一。
  3. 缺乏拦截器:未封装的axios没有预定义的请求和响应拦截器,无法方便地统一处理请求和响应的逻辑,如认证、错误处理等。
  4. API管理困难:未封装的axios无法方便地管理API接口,容易导致接口定义分散,不易查找和修改。
  5. 可扩展性受限:未封装的axios难以进行功能扩展,如添加自定义拦截器、缓存等功能。

综上所述,封装axios可以解决未封装axios的不便之处,提供更好的代码组织、可维护性和可扩展性。通过封装,可以统一配置、提供拦截器处理、方便API管理,并且使代码更加简洁、可读和易于维护。总结起来,封装axios有以下几个原因:

  • 代码复用:通过封装,可以将通用的请求逻辑封装成可重用的函数或模块,减少重复代码的编写。
  • 可维护性:将axios的配置、拦截器等逻辑封装在一处,方便维护和修改。
  • 错误处理:封装可以集中处理请求和响应的错误,提供统一的错误处理机制。
  • 接口统一管理:将API接口的定义和管理集中在一处,方便查找和修改。
  • 方便扩展:通过封装,可以轻松地扩展axios的功能,比如添加认证、缓存等功能。

3. axios 的封装

当封装axios时,可以采用不同的形式。下面分别介绍函数封装、实例封装和类封装,并给出使用TypeScript编写的具体封装示例代码:

3.1 函数封装方式

函数封装是将常用的请求封装成函数,接收参数并返回Promise对象。

import axios, {
    
     AxiosRequestConfig, AxiosResponse } from 'axios';

/**
 * 发送GET请求
 * @param url 请求URL
 * @param params 请求参数
 * @returns Promise对象,包含响应数据
 */
export function get(url: string, params?: AxiosRequestConfig['params']): Promise<AxiosResponse> {
    
    
  return axios.get(url, {
    
     params });
}

/**
 * 发送POST请求
 * @param url 请求URL
 * @param data 请求数据
 * @returns Promise对象,包含响应数据
 */
export function post(url: string, data?: any): Promise<AxiosResponse> {
    
    
  return axios.post(url, data);
}

// 在Vue组件中使用
import {
    
     get, post } from '@/api';

export default {
    
    
  methods: {
    
    
    fetchData() {
    
    
      get('/data')
        .then((response) => {
    
    
          // 处理成功响应
        })
        .catch((error) => {
    
    
          // 处理错误响应
        });
    },
    postData() {
    
    
      post('/data', {
    
     /* 数据 */ })
        .then((response) => {
    
    
          // 处理成功响应
        })
        .catch((error) => {
    
    
          // 处理错误响应
        });
    },
  },
};

3.2 实例封装方式

实例封装是创建axios实例,并设置通用的配置、拦截器等。

import axios, {
    
     AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';

class ApiClient {
    
    
  private instance: AxiosInstance;

  constructor(baseURL: string) {
    
    
    this.instance = axios.create({
    
    
      baseURL,
      timeout: 5000,
    });

    // 请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
    
    
        // 在请求发送前做一些处理
        return config;
      },
      (error) => {
    
    
        // 处理请求错误
        return Promise.reject(error);
      }
    );

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response) => {
    
    
        // 对响应数据进行处理
        return response.data;
      },
      (error) => {
    
    
        // 处理响应错误
        return Promise.reject(error);
      }
    );
  }

  /**
   * 发送GET请求
   * @param url 请求URL
   * @param params 请求参数
   * @returns Promise对象,包含响应数据
   */
  public get(url: string, params?: AxiosRequestConfig['params']): Promise<AxiosResponse> {
    
    
    return this.instance.get(url, {
    
     params });
  }

  /**
   * 发送POST请求
   * @param url 请求URL
   * @param data 请求数据
   * @returns Promise对象,包含响应数据
   */
  public post(url: string, data?: any): Promise<AxiosResponse> {
    
    
    return this.instance.post(url, data);
  }
}

// 在Vue组件中使用
import ApiClient from '@/api';

const api = new ApiClient('https://

api.example.com');

export default {
    
    
  methods: {
    
    
    fetchData() {
    
    
      api.get('/data')
        .then((response) => {
    
    
          // 处理成功响应
        })
        .catch((error) => {
    
    
          // 处理错误响应
        });
    },
    postData() {
    
    
      api.post('/data', {
    
     /* 数据 */ })
        .then((response) => {
    
    
          // 处理成功响应
        })
        .catch((error) => {
    
    
          // 处理错误响应
        });
    },
  },
};

3.3 类封装方式

类封装通过类来封装axios,封装各种请求方法和处理逻辑。例如:

import axios, {
    
     AxiosRequestConfig, AxiosResponse } from 'axios';

class ApiClient {
    
    
  private baseURL: string;
  private instance = axios.create({
    
    
    timeout: 5000,
  });

  constructor(baseURL: string) {
    
    
    this.baseURL = baseURL;

    // 请求拦截器
    this.instance.interceptors.request.use(
      (config) => {
    
    
        // 在请求发送前做一些处理
        return config;
      },
      (error) => {
    
    
        // 处理请求错误
        return Promise.reject(error);
      }
    );

    // 响应拦截器
    this.instance.interceptors.response.use(
      (response) => {
    
    
        // 对响应数据进行处理
        return response.data;
      },
      (error) => {
    
    
        // 处理响应错误
        return Promise.reject(error);
      }
    );
  }

  /**
   * 发送GET请求
   * @param url 请求URL
   * @param params 请求参数
   * @returns Promise对象,包含响应数据
   */
  public get(url: string, params?: AxiosRequestConfig['params']): Promise<AxiosResponse> {
    
    
    return this.instance.get(this.baseURL + url, {
    
     params });
  }

  /**
   * 发送POST请求
   * @param url 请求URL
   * @param data 请求数据
   * @returns Promise对象,包含响应数据
   */
  public post(url: string, data?: any): Promise<AxiosResponse> {
    
    
    return this.instance.post(this.baseURL + url, data);
  }
}

// 在Vue组件中使用
import ApiClient from '@/api';

const api = new ApiClient('https://api.xxxxxx.com');

export default {
    
    
  methods: {
    
    
    fetchData() {
    
    
      api.get('/data')
        .then((response) => {
    
    
          // 处理成功响应
        })
        .catch((error) => {
    
    
          // 处理错误响应
        });
    },
    postData() {
    
    
      api.post('/data', {
    
     /* 数据 */ })
        .then((response) => {
    
    
          // 处理成功响应
        })
        .catch((error) => {
    
    
          // 处理错误响应
        });
    },
  },
};

3.4 三种封装方式的比较

上面我们介绍了通过 函数封装实例封装类封装 三种封装方式来封装 axios。当然,它们都可以用来封装axios,它们在代码组织和使用上有一些区别。本节我们对这三种方式做一些比较。

封装方式 描述
函数封装方式 函数封装方式是最简单的封装方式,它将 axios 作为函数的参数传入,并在函数内部执行相应的请求。
这种方式适用于简单的请求场景,可以快速地发送请求并获取响应。
函数封装方式的主要优点是简单易用,没有额外的复杂性,适合于小型项目或者只有少量API请求的情况。然而,函数封装方式的可扩展性相对较差,难以处理复杂的请求逻辑和统一的错误处理。
实例封装方式 实例封装方式创建了一个axios实例,并通过给实例添加方法来封装不同类型的请求。
这种方式可以在一个实例中设置通用的请求配置,例如基础URL、拦截器等。
实例封装方式具有更好的可扩展性和灵活性,可以根据需要定义多个实例,每个实例可以有自己的配置。这种方式适用于中大型项目,可以更好地组织和管理请求代码。
类封装方式 类封装方式使用面向对象的思想,将axios封装成一个类,并通过类的方法来发送请求。
这种方式结合了函数封装和实例封装的优点,提供了更强大的封装能力和更好的代码组织结构。
类封装方式可以定义公共的请求配置和错误处理逻辑,并可以通过继承和多态的方式实现更高级的功能扩展。它适用于大型项目和需要复杂请求逻辑的场景。

总的来说,函数封装方式简单易用,实例封装方式具有一定的可扩展性和灵活性,而类封装方式则提供了最强大的封装能力和代码组织结构。实际开发中具体选择哪种方式可以取决于项目的规模、复杂性,但是一般更多地会取决于团队的开发经验,以及个人的偏好和需求。

4. 弃用 Axios 的思考

4.1 Axios 存在的主要问题

xios是一个常用的JavaScript库,用于在浏览器和Node.js中进行HTTP请求。尽管Axios是一个流行的选择,但它也有一些不足之处:

项目 描述 替代方向
体积较大 Axios的体积相对较大,这可能在某些情况下对性能产生一些负面影响。 如果项目对文件大小有较严格的要求,可以考虑使用一些轻量级的替代方案。
API 设计风格 Axios的API设计是基于Promise的,这对于处理异步请求非常方便。然而,一些开发者可能更喜欢使用基于回调的API或者async/await语法。 根据个人喜好和项目需求,选择适合的API风格可能更合适。
浏览器兼容性 尽管Axios在大多数现代浏览器中运行良好,但在某些旧版本的浏览器中可能存在兼容性问题。 如果你需要支持较旧的浏览器,可能需要考虑使用其他解决方案或者进行额外的兼容性处理。

4.2 一些现成的可选替代方案

替代方案收集中,欢迎在评论区留言推荐

方案 描述 文档链接
Fetch API Fetch API 是现代浏览器原生提供的一种用于发起网络请求的接口,它支持Promise和async/await语法。它具有较小的体积,且在大多数现代浏览器中都有良好的兼容性。 https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API
Superagent Superagent 是另一个流行的HTTP请求库,它具有简洁的API设计和较小的体积。它支持回调和Promise两种风格,并且在浏览器和Node.js中都能运行。 https://ladjs.github.io/superagent/docs/zh_CN/index.html
Fetch+AbortController 如果你只关注现代浏览器的兼容性,你可以结合使用Fetch API和AbortController来发起请求并支持请求的取消。AbortController允许你在需要时取消正在进行的请求,这在某些情况下非常有用。 https://developer.mozilla.org/zh-CN/docs/Web/API/AbortController

5. Fetch

5.1 Fetch 简介

5.1.1 什么是 Fetch

在过去,前端开发人员通常使用XMLHttpRequest对象来进行网络请求。然而,XMLHttpRequest存在一些问题,比如使用繁琐的接口、不统一的语法和难以处理错误。为了解决这些问题,W3C(World Wide Web Consortium)和Web开发社区共同努力,开发了Fetch API。Fetch是一种现代的Web API,用于在前端中进行网络请求。它提供了一种替代传统XMLHttpRequest(XHR)的方式,以更简单、灵活和统一的方式处理网络通信。Fetch API的设计目标包括:

  1. 提供一种简单而强大的方式来进行网络请求。
  2. 统一网络请求的接口和语法,使开发人员更容易理解和使用。
  3. 支持Promise对象,以便更好地处理异步请求。
  4. 提供更灵活的请求和响应处理选项。

5.1.2 Fetch与传统方式的比较

对比使用 XMLHttpRequest

XMLHttpRequest 方式相比。Fetch API相对于XMLHttpRequest具有以下优势:

项目 描述
更简洁的语法 Fetch API使用Promise和链式调用的方式,使代码更易读和组织。
内置的JSON解析 Fetch API内置了将响应数据解析为JSON的方法,不需要手动解析。
支持流数据 Fetch API可以处理流数据,而XMLHttpRequest不支持。
更灵活的请求选项 Fetch API提供了更丰富的请求选项,如headers、mode、cache等。
更好的错误处理 Fetch API使用Promise的catch方法来处理错误,比传统方式更直观。

对比使用 axios 模块

axios 的比较第三方模块对比:

对比项 描述
API设计 Fetch API的API设计更现代化和简洁,使用Promise和链式调用。而axios使用传统的回调函数方式设计API。
兼容性 Fetch API在现代浏览器中有良好的支持,但在老旧浏览器中存在兼容性问题。而axios通过封装XMLHttpRequest对象,具有更好的兼容性。
功能扩展 axios提供了一些额外的功能,如请求取消、拦截器、请求重试等,而Fetch API没有内置这些功能,需要开发人员自行实现。
请求转换 axios支持请求和响应的数据转换,可以自动将请求和响应数据转换为JSON、FormData等格式。Fetch API需要手动处理数据转换。
浏览器环境外支持 axios可以在浏览器和Node.js环境中使用,而Fetch API主要用于浏览器环境。

选择使用Fetch API还是axios取决于具体需求和项目要求。如果希望使用原生的浏览器API并且在现代浏览器中运行,可以考虑使用 Fetch API。如果需要更多的功能扩展、兼容性和数据转换支持,尚且还可以继续使用 axios。

5.1 Fetch 用法

5.2.1 快速入门

使用 Fetch API可以轻松地发起各种类型的HTTP请求并处理响应数据,本节给一个基本的Fetch请求示例:

fetch('https://api.xxxxxx.com/data')
  .then((response: Response) => {
    
    
    if (!response.ok) {
    
    
      throw new Error('网络响应不正常');
    }
    return response.json();
  })
  .then((data: any) => {
    
    
    console.log(data);
  })
  .catch((error: Error) => {
    
    
    console.error('Error:', error);
  });

这个例子中,我们使用 fetch 函数发起了一个 GET 请求,并指定了要请求的 URL。然后,我们使用 Promisethen 方法处理响应。如果响应的状态码 不是200 时我们抛出一个错误。否则,我们将响应数据解析为 JSON 格式并输出到控制台。

5.2.2 Fetch的请求选项

Fetch API提供了一些可选的请求选项,用于自定义请求的行为。以下是一些常用的选项:

选项 描述
method 指定请求的 HTTP 方法,如 GETPOSTPUTDELETE
headers 设置请求的头部信息,如 Content-TypeAuthorization
body 设置请求的主体数据,可以是字符串、FormData对象等
mode 设置请求的模式,如 corsno-corssame-origin
cache 设置请求的缓存模式,如 defaultno-storereload

例如:

const options: RequestInit = {
    
    
  method: 'POST',
  headers: {
    
    
    'Content-Type': 'application/json',
    'Authorization': 'Bearer token'
  },
  body: JSON.stringify({
    
     username: 'john', password: 'secret' })
};

fetch('https://api.example.com/login', options)
  .then((response: Response) => {
    
    
    if (!response.ok) {
    
    
      throw new Error('网络响应不正常');
    }
    return response.json();
  })
  .then((data: any) => {
    
    
    console.log(data);
  })
  .catch((error: Error) => {
    
    
    console.error('Error:', error);
  });

【注】

5.2.3 Fetch 的响应处理

Fetch API提供了多种处理响应的方法,您可以根据需要选择适合的方法。以下是一些常用的处理方法:

方法 描述
response.text() 将响应数据作为文本返回。
response.json() 将响应数据解析为JSON格式返回。
response.blob() 将响应数据解析为Blob对象返回。
response.arrayBuffer() 将响应数据解析为ArrayBuffer对象返回。

例如:

fetch('https://api.example.com/image')
  .then((response: Response) => {
    
    
    if (!response.ok) {
    
    
      throw new Error('网络响应不正常');
    }
    return response.blob();
  })
  .then((blob: Blob) => {
    
    
    const img = document.createElement('img');
    img.src = URL.createObjectURL(blob);
    document.body.appendChild(img);
  })
  .catch((error: Error) => {
    
    
    console.error('Error:', error);
  });

本例我们使用 response.blob() 方法将响应数据解析为 Blob对象。然后,我们创建一个img 元素,并将 Blob 对象的 URL 赋值给 imgsrc 属性,以显示图像。

猜你喜欢

转载自blog.csdn.net/qq_28550263/article/details/131099244