【转载】vue3 Ts axios 封装

vue3 Ts axios 封装

安装 npm install axios --S

axios的封装

  • Axios默认使用application/json作为请求头的Content-Type,数据会自动转为UTF-8格式的JSON字符串‌。
  • 若需提交表单数据(如FormData),需显式设置Content-Type: multipart/form-data; charset=UTF-8
typescript 复制代码
import axios, { AxiosError, AxiosInstance, InternalAxiosRequestConfig, AxiosResponse, AxiosRequestConfig, AxiosHeaders } from 'axios'
import qs from 'qs'
import { config } from './config'
import { ElMessage } from 'element-plus'

// 从配置文件中提取相关配置
const { base_url, request_timeout, result_code } = config

// 创建 axios 实例
const service: AxiosInstance = axios.create({
  // 设置基础 URL,所有请求都会在这个地址基础上进行拼接
  baseURL: base_url,
  // 设置请求超时时间(单位:毫秒),超过这个时间还没响应则认为请求失败
  timeout: request_timeout,
  // 允许携带凭证(如 Cookie),用于处理跨域请求时需要传递 Cookie 的情况
  withCredentials: true,
  // 设置默认请求头,这里设置为 application/json,表示发送 JSON 格式的数据
  headers: { 'Content-Type': 'application/json' },
  // 自定义参数序列化函数,用于处理请求参数的序列化
  paramsSerializer: (params: any): string => {
    // 使用 qs 库进行参数序列化,并允许使用点号表示嵌套对象
    return qs.stringify(params, { allowDots: true })
  }
})

// request 拦截器,用于在请求发送前对请求进行处理
service.interceptors.request.use(
  (config: InternalAxiosRequestConfig): InternalAxiosRequestConfig => {
    // 获取请求方法,并转换为大写
    const method = config.method?.toUpperCase()
    // 如果是 GET 请求
    if (method === 'GET') {
      // 设置请求头,防止 GET 请求缓存
      config.headers['Cache-Control'] = 'no-cache'
      config.headers['Pragma'] = 'no-cache'
    }
    // 如果是 POST 请求
    else if (method === 'POST') {
      // 获取请求头中的 Content-Type
      const contentType = config.headers['Content-Type'] || config.headers['content-type']
      // 如果 Content-Type 是 application/x-www-form-urlencoded
      if (contentType === 'application/x-www-form-urlencoded') {
        // 如果请求数据存在且不是字符串类型
        if (config.data && typeof config.data !== 'string') {
          // 使用 qs 库将请求数据序列化为 URL 编码格式的字符串
          config.data = qs.stringify(config.data)
        }
      }
    }
    // 返回处理后的配置,继续请求流程
    return config
  },
  (error: AxiosError): Promise<AxiosError> => {
    // 如果请求发生错误,返回错误的 Promise
    return Promise.reject(error)
  }
)

// response 拦截器,用于在接收到响应后对响应进行处理
service.interceptors.response.use(
  async (response: AxiosResponse<any>): Promise<any> => {
    // 获取响应数据
    let { data } = response
    // 如果响应数据不存在
    if (!data) {
      // 抛出错误,表示请求没有返回值
      throw new Error()
    }
    // 如果响应的 responseType 是 blob 或 arraybuffer(处理二进制数据,如文件下载)
    if (
      response.request.responseType === 'blob' ||
      response.request.responseType === 'arraybuffer'
    ) {
      // 如果响应的数据类型不是 application/json
      if (response.data.type !== 'application/json') {
        // 直接返回响应数据,进行文件下载等操作
        return response.data
      }
      // 如果响应的数据类型是 application/json,说明可能导出失败,将响应数据转换为 JSON 格式
      data = await new Response(response.data).json()
    }
    // 返回处理后的响应数据
    return data
  },
  (error: AxiosError): Promise<AxiosError> => {
    // 打印错误信息,用于调试
    console.log('err' + error)
    // 获取错误信息
    let { message } = error
    // 显示错误消息提示
    ElMessage.error(message)
    // 返回错误的 Promise,继续错误处理流程
    return Promise.reject(error)
  }
)

// 导出 axios 实例,供其他模块使用
export { service }

封装get post delete 方法

typescript 复制代码
import { service } from './service'
import { config } from './config'

const { default_headers } = config

// 定义请求方法的类型
type RequestMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' 

// 定义请求配置的类型
interface RequestOptions {
  method?: RequestMethod
  url?: string
  data?: any
  params?: any
  headers?: any
  responseType?: 'json' | 'blob' | 'arraybuffer'
  headersType?: string
  [key: string]: any
}

// 封装请求方法,用于统一处理请求配置
const request = (options: RequestOptions): Promise<AxiosResponse<any>> => {
  // 解构请求配置,提取 headersType 和 headers
  const { headersType, headers, ...otherOptions } = options
  // 使用 service 发起请求
  // 合并请求头,优先使用 headersType 或 default_headers,然后合并 headers
  return service({
    ...otherOptions,
    headers: {
      'Content-Type': headersType || default_headers, // 设置 Content-Type
      ...headers // 合并其他请求头
    }
  })
}

// 定义请求工具类,提供各种 HTTP 请求方法
export default {
  // GET 请求方法
  get: async <T = any>(option: RequestOptions): Promise<T> => {
    // 发起 GET 请求
    const res = await request({ method: 'GET', ...option })
    // 返回响应数据,并将其转换为指定类型
    return res.data as unknown as T
  },
  // POST 请求方法
  post: async <T = any>(option: RequestOptions): Promise<T> => {
    // 发起 POST 请求
    const res = await request({ method: 'POST', ...option })
    // 返回响应数据,并将其转换为指定类型
    return res.data as unknown as T
  },
  // 原始 POST 请求方法,返回完整的响应对象
  postOriginal: async (option: RequestOptions): Promise<AxiosResponse<any>> => {
    // 发起 POST 请求
    const res = await request({ method: 'POST', ...option })
    // 返回完整的响应对象
    return res
  },
  // DELETE 请求方法
  delete: async <T = any>(option: RequestOptions): Promise<T> => {
    // 发起 DELETE 请求
    const res = await request({ method: 'DELETE', ...option })
    // 返回响应数据,并将其转换为指定类型
    return res.data as unknown as T
  },
  // PUT 请求方法
  put: async <T = any>(option: RequestOptions): Promise<T> => {
    // 发起 PUT 请求
    const res = await request({ method: 'PUT', ...option })
    // 返回响应数据,并将其转换为指定类型
    return res.data as unknown as T
  },
  // 下载文件的请求方法
  download: async <T = any>(option: RequestOptions): Promise<T> => {
    // 发起 GET 请求,设置 responseType 为 blob,用于处理文件下载
    const res = await request({ method: 'GET', responseType: 'blob', ...option })
    // 返回响应数据,并将其转换为指定类型
    return res as unknown as Promise<T>
  },
  // 上传文件的请求方法
  upload: async <T = any>(option: RequestOptions): Promise<T> => {
    // 设置 headersType 为 multipart/form-data,用于文件上传
    option.headersType = 'multipart/form-data'
    // 发起 POST 请求
    const res = await request({ method: 'POST', ...option })
    // 返回响应数据,并将其转换为指定类型
    return res as unknown as Promise<T>
  }
}

config.ts部分

arduino 复制代码
/config.ts
type AxiosHeaders =
| 'application/json'
| 'application/x-www-form-urlencoded'
| 'multipart/form-data'

  const config: {
    base_url: string
    result_code: number | string
    default_headers: AxiosHeaders
    request_timeout: number
  } = {
    /**
     * api请求基础路径
     */
    base_url: import.meta.env.VITE_BASE_URL + import.meta.env.VITE_API_URL,
    /**
     * 接口成功返回状态码
     */
    result_code: 200,
  
    /**
     * 接口请求超时时间
     */
    request_timeout: 30000,
  
    /**
     * 默认接口请求类型
     * 可选值:application/x-www-form-urlencoded multipart/form-data
     */
    default_headers: 'application/json'
  }
  
  export { config }

版权声明:本文为CSDN博主「会飞的鱼先生」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。 原文链接:blog.csdn.net/qq_44136028...

相关推荐
程序猿阿伟6 分钟前
《不只是接口:GraphQL与RESTful的本质差异》
前端·restful·graphql
若梦plus2 小时前
Nuxt.js基础与进阶
前端·vue.js
樱花开了几轉2 小时前
React中为甚么强调props的不可变性
前端·javascript·react.js
风清云淡_A2 小时前
【REACT18.x】CRA+TS+ANTD5.X实现useImperativeHandle让父组件修改子组件的数据
前端·react.js
小飞大王6662 小时前
React与Rudex的合奏
前端·react.js·前端框架
若梦plus2 小时前
React之react-dom中的dom-server与dom-client
前端·react.js
若梦plus2 小时前
react-router-dom中的几种路由详解
前端·react.js
若梦plus2 小时前
Vue服务端渲染
前端·vue.js
Mr...Gan2 小时前
VUE3(四)、组件通信
前端·javascript·vue.js
OEC小胖胖2 小时前
渲染篇(二):解密Diff算法:如何用“最少的操作”更新UI
前端·算法·ui·状态模式·web