使用 TS 自定义封装 axios

174 阅读1分钟

原生xhr 封装 axios实现, 以及如何使TS添加类型注解, 主要使用了泛型参数,加深你对泛型参数的理解

// type/myAxios.d.ts
export type configType<T = unknown> = {
    url: string
    method?: XMLHttpRequest['method']
    dataType?: XMLHttpRequestResponseType
    data?: Record<string, unknown>
    params?: Record<string, string>
    success?: (res: T) => void
    fail?: (err: unknown) => void
    complete?: () => void
}

export interface resultType<T> {
    code: number
    data: T,
    error: null
    updateTime: number
}
// utils/myAxios.ts
// 导入请求配置类型
import type { configType } from '../type/myAxios'
/** * 自定义axios函数 * @param {configType<T>} config - 请求配置对象,包括请求方法、URL、参数、数据类型等 * @returns {Promise<T>} - 返回一个Promise,根据请求结果解析为指定类型T的数据 
 * 
*/
export function myAxios<T>(config: configType<T>) {
    // 创建一个新的Promise对象来处理异步请求 
    new Promise<T>((reslove, reject) => {
        // 创建XMLHttpRequest对象 
        const xhr = new XMLHttpRequest()
        // 处理查询参数 
        if (config.params) {
            // 创建URL查询字符串 
            const params = new URLSearchParams(config.params)
            const queryString = params.toString()
            // 将查询字符串追加到URL中 
            config.url += `?${queryString}`
        }
        // 初始化请求 
        xhr.open(config.method || 'GET', config.url)
        // 设置返回数据格式 
        xhr.responseType = config.dataType || 'json'
        // 监听请求完成事件 
        xhr.addEventListener('loadend', () => {
            // 判断请求状态码 
            if (xhr.status >= 200 && xhr.status < 300) {
                // 请求成功,解析响应数据 类型断言
                reslove(xhr.response as T)
            } else {
                // 请求失败,返回错误信息 
                return reject(xhr.response)
            }
        }) // 处理请求体参数 
        if (config.data) {
            // 设置请求头,指定数据格式为JSON 
            xhr.setRequestHeader('Content-Type', 'application/json')
            // 发送请求,数据格式为JSON字符串 
            xhr.send(JSON.stringify(config.data))
        } else {
            // 如果没有请求体数据,直接发送请求 
            xhr.send()
        }
    }).then(res => {
        // 请求成功回调 
        config.success?.(res)
    }).catch(err => {
        // 请求失败回调 
        config.fail?.(err)
    }).finally(() => {
        // 请求完成回调,无论成功或失败都会执行 
        config.complete?.()
    })
}
```App.tsx
import { resultType, dataType } from './type/myAxios'
import { useEffect } from 'react'
import { myAxios } from './utils/myAxios'

function App() {
  useEffect(() => {
    // 获取随机名言
    myAxios<resultType<dataType>>({
      url: 'https://api.xygeng.cn/one',
      success(res) {
        console.log(res)
      },
      dataType: 'json'
    })
  }, [])
  return <>this is app</>
}

export default App