基于Axios二次封装请求库,带你重构面试亮点(一)

简介: 基于Axios二次封装请求库,带你重构面试亮点

引言


在前面两篇文章中得到反馈效果不错,今天继续出第三篇,以二次封装axios为例

在我以往的面试中,听到候选人最多的就是项目中二次封装axios,但是当真正深入挖掘,往往得不到有用的信息。 那么面试官是想听到什么样的亮点呢?这篇文章我们重点分析一下,并且也可以封装自己的axios请求库。


需求


在项目中,我们可能存在这些痛点:

  • 接口统一管理
  • 支持多host问题
  • 支持区分env
  • 支持restful风格
  • 支持取消请求
  • 支持接口错误重试
  • 支持缓存
  • 支持限流


请求方法的统一封装


export class  Apis{
  public common: RequestOptions;
  // 默认的server配置
  public base!: string;
  // server服务的集合
  public serverMap: ServerMap;
  // 对象形式的请求方法集合
  public apiMap: ApisMap;
  // 挂载所有请求方法的集合对象
  public apis: ApisInstance;
  // axios实例化对象
  public instance: AxiosInstance;
  constructor(common?: RequestOptions, serverMap?: ServerMap, apiMap?: ApisMap) {
  }
  public get<T extends Record<string, any> = any>(url: string, request: RequestOptions): Promise<RestyResponse<T>> {
    request = { ...request, method: 'GET' };
    return this.request(url, request);
  }
  public delete<T extends Record<string, any> = any>(url: string, request: RequestOptions): Promise<RestyResponse<T>> {
    request = { ...request, method: 'DELETE' };
    return this.request(url, request);
  }
  public post<T extends Record<string, any> = any>(url: string, request: RequestOptions): Promise<RestyResponse<T>> {
    request = { ...request, method: 'POST' };
    return this.request(url, request);
  }
  public put<T extends Record<string, any> = any>(url: string, request: RequestOptions): Promise<RestyResponse<T>> {
    request = { ...request, method: 'PUT' };
    return this.request(url, request);
  }
  public patch<T extends Record<string, any> = any>(url: string, request: RequestOptions): Promise<RestyResponse<T>> {
    request = { ...request, method: 'PATCH' };
    return this.request(url, request);
  }
  public request<T extends Record<string, any> = any>(url: string, request: RequestOptions): Promise<RestyResponse<T>> {
    const rest = request.rest || {};
    let path = url;
    if (Object.keys(rest).length) {
      path = this.restful(url, rest);
    }
    // 合并公共配置
    const options = { ...this.common, ...request };
    return this.instance.request({
      ...options,
      url: path,
    });
  }
}


接口统一管理


在项目中,实际每个请求的写法都是一样的,开发过程中,我不想在每个页面都重复写请求方法,我想通过JSON配置的方式做接口统一管理,比如:

在Home Module下,新建apis.ts文件:

export default {
  getBaseInfo: {
    method: 'get',
    url: '/base/get'
  },
  getBaseRestInfo: {
    method: 'get',
    url: '/base/info'
  }
}

实现:

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import {
  ApisMap,
  ServerMap,
  ApisInstance,
  ApisConfig,
  ResolvedFn,
  RejectedFn,
  Middleware,
  Rest
} from './types'
class Apis {
  base: string
  serverMap: ServerMap
  apiMap: ApisMap
  instance: ApisInstance
  axiosInstance: AxiosInstance
  constructor(serverMap: ServerMap, apiMap: ApisMap, common?: AxiosRequestConfig) {
    /**
     * 支持公共配置
     */
    this.axiosInstance = axios.create(common)
    this.serverMap = serverMap
    this.apiMap = apiMap
    this.instance = {}
    this.base = this.getDefault()
    this.combine2Request()
  }
  /**
   * 获取默认的配置
   */
  getDefault(): string {
    let base = ''
    for (const key of Object.keys(this.serverMap)) {
      /**
       * 找到默认的配置值
       */
      if (this.serverMap[key].default) {
        base = key
      }
    }
    if (!base) {
      console.error('apis: 找不到默认服务器配置')
    }
    return base
  }
  combine2Request(): void {
    for (const key of Object.keys(this.apiMap)) {
      this.instance[key] = (config?: ApisConfig) => {
        let result: ApisConfig = this.apiMap[key]
        if (config) {
          result = this.rest2Combine(this.apiMap[key], config)
        }
        return this.axiosInstance.request(result)
      }
    }
  }
}
export default createInstance


支持多host


应用可能需要跟多个服务交互,这时候涉及多host,我们想统一处理:

  • 定义serverMap
  • serverMap对象定义了两个服务:baseServerapi-test
  • 对于每个服务,都提供了一个baseMap对象来描述不同环境下的base URLs。
  • baseServer有一个default属性设置为true,表示它可能是默认选择的服务器。
  • 定义apiMap
  • apiMap对象定义了两个API:getBaseInfogetBaseRestInfo
  • 每个API都有一个HTTP方法(method)和一个URL路径(url)。
import createInstance from 'apis'
import { ApisMap } from 'apis/types'
const serverMap = {
  baseServer: {
    baseMap: {
      localprod: '',
      prod: 'https://wwww.baidu.com',
      stage: 'https://wwww.baidu.com',
      test: 'https://wwww.baidu.com',
      dev: 'https:/wwww.baidu.com',
      local: 'http://127.0.0.1:4320',
      baseURL: 'https://localhost:8080'
    },
    default: true
  },
  'api-test': {
    baseMap: {
      localprod: '',
      prod: 'https://www.baidu.com',
      stage: 'https://www.baidu.com',
      test: 'https://www.baidu.com',
      dev: 'https:/www.baidu.com',
      local: `http://127.0.0.1:4320`,
      baseURL: 'https://localhost:8080'
    }
  }
}
const apiMap: ApisMap = {
  getBaseInfo: {
    method: 'get',
    url: '/base/get'
  },
  getBaseRestInfo: {
    method: 'get',
    url: '/base/get/:id/kill/:test'
  }
}
let apis = createInstance(serverMap, apiMap)
apis.getBaseInfo({ params: { name: 'linwu' } }).then(res => {
  console.log(res)
})

实现

   /**
   * 给个请求
   * 配置正确的baseURL
   * 如果没有baseURL就读默认的
   */
  formatConfigUrl(): void {
    for (const key of Object.keys(this.apiMap)) {
      const item = this.apiMap[key]
      if (!item.server) {
        item.server = this.base
      }
      this.apiMap[key] = { ...this.serverMap[item.server], ...item }
    }
  }

目录
相关文章
|
9天前
封装axios的get、post方法
本文介绍了如何封装axios的get和post方法,并展示了具体的代码实现,包括使用axios创建实例、设置请求拦截器以及定义get和post函数。
24 2
|
11天前
|
JavaScript 前端开发 API
网络请求库 – axios库
网络请求库 – axios库
|
24天前
|
JavaScript 前端开发 开发者
vue中使用axios请求post接口,请求会发送两次
vue中使用axios请求post接口,请求会发送两次
|
5天前
|
JavaScript 前端开发 Java
SpringBoot项目的html页面使用axios进行get post请求
SpringBoot项目的html页面使用axios进行get post请求
18 6
|
2月前
|
Python
axios的get请求传入数组参数
axios的get请求传入数组参数
|
7天前
axios全局做节流,解决多次点击导致多次请求接口
本文介绍了如何在Axios请求中实现全局节流,以防止用户快速多次点击导致重复发送相同请求的问题。
23 2
|
9天前
|
前端开发 JavaScript
React配合axios请求拦截校验session,403跳转至登陆页面
React中使用axios进行请求拦截,通过自定义事件监听和响应拦截实现403状态码时的自动登录页面跳转。
15 2
|
12天前
|
JSON 资源调度 JavaScript
Vue框架中Ajax请求的实现方式:使用axios库或fetch API
选择 `axios`还是 `fetch`取决于项目需求和个人偏好。`axios`提供了更丰富的API和更灵活的错误处理方式,适用于需要复杂请求配置的场景。而 `fetch`作为现代浏览器的原生API,使用起来更为简洁,但在旧浏览器兼容性和某些高级特性上可能略显不足。无论选择哪种方式,它们都能有效地在Vue应用中实现Ajax请求的功能。
18 4
|
2月前
|
JSON JavaScript 前端开发
【Vue面试题二十四】、Vue项目中有封装过axios吗?主要是封装哪方面的?
这篇文章讨论了在Vue项目中封装axios的最佳实践,包括设置接口请求前缀、请求头、状态码、请求方法的封装,以及如何使用请求和响应拦截器来处理token和响应状态,从而简化HTTP请求的配置和错误处理,提高代码的可维护性。
【Vue面试题二十四】、Vue项目中有封装过axios吗?主要是封装哪方面的?
|
2月前
|
JavaScript 前端开发 Java
面试官:假如有几十个请求,如何去控制并发?
面试官:假如有几十个请求,如何去控制并发?
下一篇
无影云桌面