封装axios的两种方式

这篇具有很好参考价值的文章主要介绍了封装axios的两种方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

作为前端工程师,经常需要对axios进行封装以满足复用的目的。在不同的前端项目中使用相同的axios封装有利于保持一致性,有利于数据之间的传递和处理。本文提供两种对axios进行封装的思路。

1. 将请求方式作为调用参数传递进来

  1. 首先导入了axios, AxiosInstance和AxiosResponse模块,用于创建一个http请求的实例和处理响应结果。
  2. 定义了一个getBaseUrl函数,用于获取请求的基础URL。
  3. 创建了httpProto实例,使用axios.create方法进行创建。并配置了请求的超时时间为5000ms,不携带凭证,设置请求的Content-Type为application/json;charset=UTF-8,并允许跨域访问。
  4. 添加了一个请求拦截器,通过httpProto.interceptors.request.use方法,对请求进行处理。首先使用getBaseUrl函数获取基础URL,并将其添加到请求的baseURL属性中。然后通过getToken函数获取凭证,如果凭证存在,则将其添加到请求的Authorization头部字段中。最后返回处理后的请求配置。
  5. 添加了一个响应拦截器,通过httpProto.interceptors.response.use方法,对响应进行处理。首先获取响应的data字段,然后判断data.result的值,如果为0则表示请求成功,直接返回data。否则将返回一个失败的Promise,reject的值为data。
  6. 定义了一个http函数,用于发送请求。这个函数接收一个method参数和其他参数(rest),然后通过httpProto[method](...rest)的形式调用httpProto实例的对应方法发送请求。
  7. 定义了一个urls对象,用于存储可供使用的URL路径,其中有一个示例路径example。
  8. 定义了一个methods对象,用于存储常用的请求方法名称,包括get、post和delete

完整的代码如下所示:

import axios, { AxiosInstance, AxiosResponse } from "axios";
import { getToken } from "./token";

// 获取请求的基础URL
const getBaseUrl = () => `http://${window.constant.serverIp}:8888}`;

// 创建http请求的实例对象
const httpProto: AxiosInstance = axios.create({
  timeout: 5000,
  withCredentials: false,
  headers: {
    'Content-Type': 'application/json;charset=UTF-8',
    'Access-Control-Allow-Origin': '*',
  }
});

// 添加请求拦截器
httpProto.interceptors.request.use((config: any) => {
  // 配置baseURL
  config.baseURL = getBaseUrl();
  // 获取凭证
  const token = getToken();
  if (token) {
    // 如果有凭证就加上此凭证
    config.headers.Authorization = `${token}`;
  }
  return config;
}, (error) => {
  return Promise.reject(error)
});

// 添加响应拦截器
httpProto.interceptors.response.use(
  (response: AxiosResponse) => {
    const { data } = response
    // 统一处理响应结果
    if (data.result === 0) {
      return data;
    } else {
      return Promise.reject(data);
    }
  },
  (error) => {
    // 统一处理错误信息
    return Promise.reject(error);
  }
);

// 将httpProto实例,也就是AxiosInstance实例对象封装起来
const http = (method: string, ...rest: any) => {
  return httpProto[method](...rest);
}

// 可供使用的urls
const urls = {
  example: `/prod/example`,
}

const methods = {
  get: 'get',
  post: 'post',
  delete: 'delete',
}

export { http, urls, methods };

2. 直接调用某请求方式对应的请求方法

  1. 导入了axios模块的相关类型和函数。
  2. 定义了printLog函数,用于处理日志输出
  3. 定义了IResponse接口,表示请求响应对象的格式。
  4. 定义了RequestParams接口,表示发送请求的配置项的格式。
  5. 定义了IHttp接口,表示封装对象支持的请求方式/方法。
  6. 定义了req对象,用于向外暴露支持的请求方法。
  7. 定义了methods数组,表示支持的请求方式类型。
  8. 使用forEach方法遍历methods数组,逐步构造req对象上的各个方法
  9. 在每个方法的构造过程中,进行以下步骤:
    • 参数合并,将默认的responseType设置为'json'。
    • 从params对象中解构需要的参数。
    • 使用axios.create方法创建一个AxiosInstance实例对象。
    • 创建请求头对象,并设置一些常用的请求头信息。
    • 构造请求配置对象AxiosRequestConfig
    • 根据请求方式对请求配置进行修正,主要是将data赋值到相应的字段中。
    • 添加请求拦截器,并在成功和失败的情况下返回配置。
    • 添加响应拦截器,并在成功和失败的情况下返回处理结果。
    • 构造请求成功的回调函数,对返回数据进行格式化的操作。
    • 构造请求失败的回调函数,处理错误日志和断网情况。
    • 发送请求并将请求结果作为函数的返回值。
  10. 默认导出req对象。

以下是加上注释的完整代码:

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

// 日志处理,可定制
const printLog = console;

// 作为被Promise包裹的请求响应对象的格式
export interface IResponse {
  code: number;
  msg: string;
  result: {
    lastOperaTime: number;
    data: any;
  };
}

// 发送请求的配置项的格式
export interface RequestParams {
  url: string;
  baseUrl?: string;
  data?: object;
  filter?: boolean;
  responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream';
  headers?: any;
  timeout?: number;
}

// 封装对象支持的请求方式/方法
interface IHttp {
  get?: (params: RequestParams) => Promise<any>;
  post?: (params: RequestParams) => Promise<any>;
  put?: (params: RequestParams) => Promise<any>;
  patch?: (params: RequestParams) => Promise<any>;
  delete?: (params: RequestParams) => Promise<any>;
}

// 支持的请求方式类型
export type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';

// 向外暴露出去的对象
const req: IHttp = {};

// 支持的请求类型
const methods: HttpMethod[] = ['get', 'post', 'put', 'patch', 'delete'];

// 遍历methods数组,逐步构造req对象
methods.forEach((_m: HttpMethod) => {
  // 使用遍历的方式对req对象上的各个方法进行构造
  req[_m] = (params: RequestParams) => {
    // 1. 构造参数合并
    params = {
      ...params,
      responseType: params.responseType || 'json',
    };

    // 2. 从使用对象方法的形参上结构出必要的参数
    const {
      url, // 服务器地址
      data, // 有效载荷
      filter = true, // 过滤器
      responseType, // 返回类型
      timeout, // 超时时间
    } = params;

    // 3. 使用axios创建AxiosInstance实例对象
    const instance = axios.create({
      baseURL: params.baseUrl ?? `http://${window.location.hostname}`,
      timeout,
    });

    // 4. 创建请求头对象
    const headers = {
      lastOperaTime: Date.now(), // 时间戳
      token: getToken(), // 凭证
      lang: getLocalLocale(), // 语言
      Accept: 'application/json', // 接受返回数据的类型
      'Content-Type': 'application/json; charset=utf-8', // 内容格式
    };

    // 5. 请求配置
    const axiosConfig: AxiosRequestConfig = {
      method: _m, // 请求方法
      url, // 服务器地址
      headers: {
        // 合并请求头
        ...headers,
        ...(params.headers || {}),
      },
      responseType, // 返回值类型
    };

    // 6. 针对不同的请求类型需要对请求配置进行修正
    if (data) {
      // 对于有效载荷,不同的请求方式携带信息的方式是不同的,在这里做了区分
      if (_m === 'get') {
        axiosConfig.params = data;
      } else if (data instanceof FormData) {
        axiosConfig.data = data;
      } else {
        axiosConfig.data = data;
      }
    }

    // 添加请求拦截器
    instance.interceptors.request.use(
      // 占位
      (config: any) => {
        return config;
      },
      // 失败则返回失败
      (error: any) => {
        return Promise.reject(error);
      }
    );

    // 7. 添加响应拦截器
    instance.interceptors.response.use(
      // 成功的回调,将发起请求的参数作为第二参数回传
      (res: any) => handleSuccess(res, params),
      // 失败的回调,将发起请求的参数作为第二参数回传
      (err: any) => handleError(err, params)
    );

    // 8. 构造请求成功的回调函数 -- 主要是对返回数据进行格式化的操作
    function handleSuccess(response: AxiosResponse<IResponse>, requestParams: RequestParams) {
      if (response.data) {
        // 解构数据
        const { code, msg, result } = response.data;
        if (code !== 0) {
          printLog.error(msg);
        }

        return filter ? result?.data ?? result : response.data;
      } else {
        printLog.error('incorrect data format');
        return response.data;
      }
    }

    // 9. 构造请求失败的回调函数
    function handleError(err: AxiosError, requestParams: RequestParams) {
      if (err.response) {
        printLog.error(`api: ${requestParams.url}: ${err.response.status}`);
      }
      if (err instanceof Error) {
        if (err.message) {
          printLog.error(err.message);
        }
      }
      if (!window.navigator.onLine) {
        // 处理断网情况
        printLog.error('netwrok error');
      }
      return Promise.reject(err);
    }

    // 10. 发送请求并将请求结果(Promise对象)作为函数的返回值
    return instance.request(axiosConfig);
  };
});

export default req;

 给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:web前端面试题库

 文章来源地址https://www.toymoban.com/news/detail-721032.html

到了这里,关于封装axios的两种方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • axios和vite在本地开发环境配置代理的两种方式,五分钟学会

    如果你使用vue或者react开发,就得使用axios吧,然后为了解决跨域问题,就得使用vite配置吧,那怎么协调配置它们两个才能正常工作呢? 正常的流程:配置axios的baseURL,然后配置vite的proxy 配置axios的baseURL: 然后再配置vite的proxy:在vite.config.js中配置 如果你想将路径重写也是

    2024年02月04日
    浏览(38)
  • vue实现导出excel的两种方式

    通过vue实现导出有两种方式: (1)后端返回的是一个地址,直接拼接打开下载就行 (2)后端返回的是文件流的形式,这个时候就需要在请求头还有返回值的地方设置一下 (1)设置请求头 (2)设置返回结果,处理返回我文件流 (3)附加说明 有的时候做到上述几步还是不

    2024年02月12日
    浏览(51)
  • Vue中强制更新数据的两种方式

    有时候我们发现修改了数据源后视图并没有更新,这里提供两种解决方案 Vue中强制更新数据的方法有两种。 方法一: 使用forceUpdate强制渲染,更新视图和数据。 注:全局强制刷新,性能消耗高。 方法二: this.$set()方法是Vue自带的可对数组和对象进行赋值,并触发监听的方法

    2024年02月11日
    浏览(54)
  • vue前端实现上传文件的两种方式

    1.使用form表单的形式 第一种方式就是使用FormData的方式进行上传 html代码: JS代码: 2.使用element-ui的el-upload的方式进行上传 这里我是根据需求封装了一个组件

    2024年02月11日
    浏览(44)
  • vue 生成二维码的两种方式

    方式一:qrcode(无 icon 图标) 完整代码 方式二:vue-qr(有 icon 图标) 官网地址:vue-qr - npm import 引入方式 完整代码 相关配置属性 属性名 含义 text 编码内容 correctLevel 容错级别(0 - 3) size 尺寸,长宽一致, 包含外边距 margin 二维码图像的外边距,默认 20px colorDark 实点的颜色

    2024年02月15日
    浏览(41)
  • Java 获取小程序码的两种方式

    目前小程序推出了自己的识别码,小程序码, 圆形的码看起来比二维码好看。 本文总结微信小程序的获取小程序二维码的接口开发。官方地址 主要内容摘抄自微信小程序的API文档,java接口开发是自己总结开发。 通过后台接口可以获取小程序任意页面的二维码,扫描该二维

    2024年02月14日
    浏览(38)
  • Vue3使用全局函数或变量的两种常用方式

    例如:想要在index.ts中创建getAction函数,并可以全局使用: 方式一:使用依赖注入(provide/inject) 在main.ts中进行挂载: 在要使用的页面注入: 方式二:使用 app.config.globalProperties 和 getCurrentInstance() app.config.globalProperties:一个用于注册能够被应用内所有组件实例访问到的全局

    2024年02月12日
    浏览(45)
  • 使用Vue脚手架配置代理服务器的两种方式

    本文主要介绍使用Vue脚手架配置代理服务器的两种方式 注意:Vue脚手架给我们提供了两种配置代理服务器的方式,各有千秋,使用的时候只能二选一,不能同时使用 除了cros和jsonp,还有一种代理方式,这种用的相对来说也很多, 一般代理服务器 这个概念很好理解,相当于生

    2024年02月02日
    浏览(69)
  • 学习笔记230810--vue项目中get请求的两种传参方式

    问题描述 今天写了一个对象方式传参的get请求接口方法,发现没有载荷,ip地址也没有带查询字符串,数据也没有响应。 代码展示 错误分析 实际上这里的 query 是对象方式带参跳转的参数名,而get方法对象方式传参的参数名是parmas 解决方法 get请求有两种带参的方式 方式1 :

    2024年02月10日
    浏览(44)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包