跳转到主内容
websoft网络软件专家 - 深耕网络技术,打造实用软件!

如何用TypeScript封装axios?

大家好,我是陈景序,今天来跟大家聊聊如何用TypeScript封装axios,让我们的Web开发更加高效和规范。

一、定义类型

首先,我们需要定义一些类型,以便更好地管理axios的配置和响应。

// type.ts
import type { AxiosRequestConfig } from 'axios'

export interface httpRequestConfig extends AxiosRequestConfig {
  baseURL?: string
  headers?: any
  timeout?: number
  apiType?: string
  json?: boolean
  form?: [boolean, string]
  formUpload?: [boolean, string]
}

// 定义通用响应结构
export interface ApiResponse {
  code: number
  data: T
  message: string
}

二、创建axios实例

接下来,我们创建一个axios实例,并添加一些基础配置和拦截器。

// http.ts
import axios, {
  AxiosInstance,
  AxiosRequestConfig,
  AxiosResponse,
  AxiosError
} from 'axios'
import { httpRequestConfig, ApiResponse } from './types'
import { showToast } from 'vant'
import { API as configApi } from '@/conf/index'
import { userCommonStoreHook } from '@/stores/modules/common'
import * as qs from 'querystring'

// 获取接口根路径
const isProd = import.meta.env.MODE === 'production'
const BASE_PATH: any = isProd ? configApi.production : configApi.development

// 导出Request类,可以用来自定义传递配置来创建实例
export class Request {
  // axios 实例
  public instance: AxiosInstance
  // 基础配置
  private baseConfig: httpRequestConfig = {
    headers: {
      'X-Requested-With': 'XMLHttpRequest',
      'Content-Type': 'application/json; charset=UTF-8'
    },
    timeout: 1000 * 60 // 设置超时时间
  }

  constructor(options: httpRequestConfig) {
    this.instance = axios.create(Object.assign(this.baseConfig, options))
    this.instance.interceptors.request.use(
      (options: httpRequestConfig) => {
        // 简化类型设置
        const headers = (options.headers = options.headers || {})

        if (options.form) {
          headers['Content-Type'] =
            'application/x-www-form-urlencoded; charset=UTF-8'
          delete options.form
        }
        if (options.formUpload) {
          headers['Content-Type'] = 'multipart/form-data; charset=UTF-8'
          delete options.formUpload
        }
        // 校验post数据格式
        const contentType = headers['Content-Type']
        if (
          typeof options.data === 'object' &&
          contentType &&
          String(contentType).indexOf('application/x-www-form-urlencoded') > -1
        ) {
          options.data = qs.stringify(options.data)
        }

        let url: any = options.url
        let ajaxPath = BASE_PATH[options.apiType || 'defaultAjaxPath']
        if (ajaxPath && !url.startsWith('http') && !url.startsWith('https')) {
          options.url = ajaxPath + url
        }
        return options
      },
      (error: AxiosError) => {
        return Promise.reject(error)
      }
    )

    this.instance.interceptors.response.use(
      (response: AxiosResponse) => {
        return response.data
      },
      (error: any) => {
        if (error.response) {
          const data = error.response.data
          const status = error.response.status
          let errMessage = data.message || '服务忙,请稍后重试(error)'
          // ...(省略错误处理代码)
        } else {
          // ...(省略错误处理代码)
        }
        return Promise.reject(error)
      }
    )
  }

  // 定义请求方法
  public request(config: AxiosRequestConfig): Promise {
    return this.instance.request(config)
  }

  public get(config?: AxiosRequestConfig): Promise>> {
    return this.instance.get(config?.url as string, config)
  }

  public post(config?: AxiosRequestConfig): Promise>> {
    return this.instance.post(config?.url as string, config?.data, config)
  }

  public put(config?: AxiosRequestConfig): Promise>> {
    return this.instance.put(config?.url as string, config?.data, config)
  }

  public delete(config?: AxiosRequestConfig): Promise>> {
    return this.instance.delete(config?.url as string, config)
  }
}

// 默认导出Request实例
export default new Request({})

三、环境配置

最后,我们需要配置环境信息,以便在不同的环境下使用不同的API路径。

/*
 * @Desc         : 环境配置信息
 * @Autor        : ZYH
 * @Date         : 2023-08-17 16:45:28
 * @LastEditors  : ZYH
 * @LastEditTime : 2023-08-17 16:47:58
 */

export const API = {
  // 开发环境
  development: {
    DEFAULT: import.meta.env.BASE_URL,
    defaultAjaxPath: '/webspiderweb'
  },
  // 生产环境
  production: {
    DEFAULT: import.meta.env.BASE_URL,
    defaultAjaxPath: '/webspiderweb'
  }
}

const isProd = import.meta.env.MODE === 'production'
export const BASE_CONFIG: AnyObject = isProd ? API.production : API.development

这样,我们就完成了使用TypeScript封装axios的过程。通过封装,我们可以更好地管理API请求,提高代码的可维护性和可读性。

如果你对Web开发有任何疑问,欢迎关注websoft网络软件专家,了解更多精彩内容。

相关文章