• 封装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

    完整的代码如下所示:

    1. import axios, { AxiosInstance, AxiosResponse } from "axios";
    2. import { getToken } from "./token";
    3. // 获取请求的基础URL
    4. const getBaseUrl = () => `http://${window.constant.serverIp}:8888}`;
    5. // 创建http请求的实例对象
    6. const httpProto: AxiosInstance = axios.create({
    7. timeout: 5000,
    8. withCredentials: false,
    9. headers: {
    10. 'Content-Type': 'application/json;charset=UTF-8',
    11. 'Access-Control-Allow-Origin': '*',
    12. }
    13. });
    14. // 添加请求拦截器
    15. httpProto.interceptors.request.use((config: any) => {
    16. // 配置baseURL
    17. config.baseURL = getBaseUrl();
    18. // 获取凭证
    19. const token = getToken();
    20. if (token) {
    21. // 如果有凭证就加上此凭证
    22. config.headers.Authorization = `${token}`;
    23. }
    24. return config;
    25. }, (error) => {
    26. return Promise.reject(error)
    27. });
    28. // 添加响应拦截器
    29. httpProto.interceptors.response.use(
    30. (response: AxiosResponse) => {
    31. const { data } = response
    32. // 统一处理响应结果
    33. if (data.result === 0) {
    34. return data;
    35. } else {
    36. return Promise.reject(data);
    37. }
    38. },
    39. (error) => {
    40. // 统一处理错误信息
    41. return Promise.reject(error);
    42. }
    43. );
    44. // 将httpProto实例,也就是AxiosInstance实例对象封装起来
    45. const http = (method: string, ...rest: any) => {
    46. return httpProto[method](...rest);
    47. }
    48. // 可供使用的urls
    49. const urls = {
    50. example: `/prod/example`,
    51. }
    52. const methods = {
    53. get: 'get',
    54. post: 'post',
    55. delete: 'delete',
    56. }
    57. 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对象。

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

    1. import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
    2. // 日志处理,可定制
    3. const printLog = console;
    4. // 作为被Promise包裹的请求响应对象的格式
    5. export interface IResponse {
    6. code: number;
    7. msg: string;
    8. result: {
    9. lastOperaTime: number;
    10. data: any;
    11. };
    12. }
    13. // 发送请求的配置项的格式
    14. export interface RequestParams {
    15. url: string;
    16. baseUrl?: string;
    17. data?: object;
    18. filter?: boolean;
    19. responseType?: 'arraybuffer' | 'blob' | 'document' | 'json' | 'text' | 'stream';
    20. headers?: any;
    21. timeout?: number;
    22. }
    23. // 封装对象支持的请求方式/方法
    24. interface IHttp {
    25. get?: (params: RequestParams) => Promise;
    26. post?: (params: RequestParams) => Promise;
    27. put?: (params: RequestParams) => Promise;
    28. patch?: (params: RequestParams) => Promise;
    29. delete?: (params: RequestParams) => Promise;
    30. }
    31. // 支持的请求方式类型
    32. export type HttpMethod = 'get' | 'post' | 'put' | 'patch' | 'delete';
    33. // 向外暴露出去的对象
    34. const req: IHttp = {};
    35. // 支持的请求类型
    36. const methods: HttpMethod[] = ['get', 'post', 'put', 'patch', 'delete'];
    37. // 遍历methods数组,逐步构造req对象
    38. methods.forEach((_m: HttpMethod) => {
    39. // 使用遍历的方式对req对象上的各个方法进行构造
    40. req[_m] = (params: RequestParams) => {
    41. // 1. 构造参数合并
    42. params = {
    43. ...params,
    44. responseType: params.responseType || 'json',
    45. };
    46. // 2. 从使用对象方法的形参上结构出必要的参数
    47. const {
    48. url, // 服务器地址
    49. data, // 有效载荷
    50. filter = true, // 过滤器
    51. responseType, // 返回类型
    52. timeout, // 超时时间
    53. } = params;
    54. // 3. 使用axios创建AxiosInstance实例对象
    55. const instance = axios.create({
    56. baseURL: params.baseUrl ?? `http://${window.location.hostname}`,
    57. timeout,
    58. });
    59. // 4. 创建请求头对象
    60. const headers = {
    61. lastOperaTime: Date.now(), // 时间戳
    62. token: getToken(), // 凭证
    63. lang: getLocalLocale(), // 语言
    64. Accept: 'application/json', // 接受返回数据的类型
    65. 'Content-Type': 'application/json; charset=utf-8', // 内容格式
    66. };
    67. // 5. 请求配置
    68. const axiosConfig: AxiosRequestConfig = {
    69. method: _m, // 请求方法
    70. url, // 服务器地址
    71. headers: {
    72. // 合并请求头
    73. ...headers,
    74. ...(params.headers || {}),
    75. },
    76. responseType, // 返回值类型
    77. };
    78. // 6. 针对不同的请求类型需要对请求配置进行修正
    79. if (data) {
    80. // 对于有效载荷,不同的请求方式携带信息的方式是不同的,在这里做了区分
    81. if (_m === 'get') {
    82. axiosConfig.params = data;
    83. } else if (data instanceof FormData) {
    84. axiosConfig.data = data;
    85. } else {
    86. axiosConfig.data = data;
    87. }
    88. }
    89. // 添加请求拦截器
    90. instance.interceptors.request.use(
    91. // 占位
    92. (config: any) => {
    93. return config;
    94. },
    95. // 失败则返回失败
    96. (error: any) => {
    97. return Promise.reject(error);
    98. }
    99. );
    100. // 7. 添加响应拦截器
    101. instance.interceptors.response.use(
    102. // 成功的回调,将发起请求的参数作为第二参数回传
    103. (res: any) => handleSuccess(res, params),
    104. // 失败的回调,将发起请求的参数作为第二参数回传
    105. (err: any) => handleError(err, params)
    106. );
    107. // 8. 构造请求成功的回调函数 -- 主要是对返回数据进行格式化的操作
    108. function handleSuccess(response: AxiosResponse, requestParams: RequestParams) {
    109. if (response.data) {
    110. // 解构数据
    111. const { code, msg, result } = response.data;
    112. if (code !== 0) {
    113. printLog.error(msg);
    114. }
    115. return filter ? result?.data ?? result : response.data;
    116. } else {
    117. printLog.error('incorrect data format');
    118. return response.data;
    119. }
    120. }
    121. // 9. 构造请求失败的回调函数
    122. function handleError(err: AxiosError, requestParams: RequestParams) {
    123. if (err.response) {
    124. printLog.error(`api: ${requestParams.url}: ${err.response.status}`);
    125. }
    126. if (err instanceof Error) {
    127. if (err.message) {
    128. printLog.error(err.message);
    129. }
    130. }
    131. if (!window.navigator.onLine) {
    132. // 处理断网情况
    133. printLog.error('netwrok error');
    134. }
    135. return Promise.reject(err);
    136. }
    137. // 10. 发送请求并将请求结果(Promise对象)作为函数的返回值
    138. return instance.request(axiosConfig);
    139. };
    140. });
    141. export default req;

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

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

    地址:web前端面试题库

     

  • 相关阅读:
    py2_Python 3 的六大数据类型
    B F C
    深度学习基础-2
    QT实现简易时钟
    由世界第一个AI软件工程师Devin引发的热潮背后----程序员到底会不会被代替?AI发展至如今是否初衷已变?
    wordpress 添加版权信息
    java集合类史上最细讲解 - TreeSet,TreeMap篇
    【配电网重构】基于yalmip求解含sop+二阶锥配电网重构附matlab代码
    大模型高效微调-LoRA原理详解和训练过程深入分析
    【毕业设计】基于单片机红外热成像仪 - stm32 物联网 嵌入式
  • 原文地址:https://blog.csdn.net/weixin_42981560/article/details/134018279