使用typescript二次封装axios

一、目的

防止短时间内同一接口未响应,再次发起请求

二、代码实现

1、定义类型

// 响应的结果
interface IResponse<T>{
    code: number,
    error: string,
    result: T
}


interface IUrlConfig {
    url: string,
    method: 'get' | 'post' | 'delete' | 'put'
}


interface IRequestConfig {
    [key: string]: IUrlConfig
}


interface IConfig {
    // 请求参数
    data?: any,
    // 请求结果的处理器
    handler?: any
}

2、实现一次封装

封装请求拦截器和响应拦截器

import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from "axios";

class Axios {
    static instance: AxiosInstance | undefined = undefined
    protected constructor() { }

    static createInstance(): AxiosInstance {
        let instance = Axios.instance || axios.create({
            baseURL: '',
            timeout: 5000
        })

        // 请求拦截器
        this.requestInterceptors(instance)

        // 响应拦截器
        this.responseInterceptors(instance)

        return instance
    }

    // 请求拦截器
    protected static requestInterceptors(instance: AxiosInstance) {
        instance.interceptors.request.use((config: AxiosRequestConfig) => {
            // 配置token
            config.headers!['token'] = 'token'
            return config
        }, error => {
            Promise.reject(error)
        })
    }

    // 响应拦截器
    protected static responseInterceptors(instance: AxiosInstance) {
        instance.interceptors.response.use((response: AxiosResponse<IResponse<any>>) => {
            if (response.data.code === 401) {
                console.log('处理401事情')
            }
            return response.data
        }, error => {
            Promise.reject(error)
        })
    }
}

export default Axios.createInstance()

3、实现二次封装

封装请求的对象

// 导入一次封装中的axios实例
import { AxiosResponse } from 'axios';
import axios from './Axios';

class AxiosServer {
    [key: string]: { [key: string]: any }
    constructor() { }

    // 设置请求属性 requestConfig login: { url: 'api/puglic/login', method: 'post' }
    // 设置属性后,最终请求方式是 api.public.login()  api就是AxiosServer的实例
    setOptions(moduleName: string, requestConfig: IRequestConfig): void {
        Object.keys(requestConfig).forEach(key => {
            this[moduleName][key] = this.request.bind(this, moduleName, key, requestConfig[key])
            // 设置锁
            this[moduleName][key].state = 'unlocked'
        })
    }

    // 请求 
    request<T>(moduleName: string, requestName: string, urlConfig: IUrlConfig, config: IConfig): Promise<IResponse<T>> {
        const method = urlConfig.method || 'get'
        const url = urlConfig.url
        const params = config.data
        const ctx = this

        return new Promise((resolve, reject) => {
            // 默认处理响应结果的处理方法
            const defaultHandler = (response: IResponse<T>) => {
                resolve(response)
            }

            // 如果没有传自定义的 handler就使用默认的handler
            const handler = config.handler || defaultHandler

            // 请求后的回调
            const callback = (response: AxiosResponse<IResponse<T>>) => {
                // 请求已经响应, 解除当前请求的锁
                ctx[moduleName][requestName].state = 'unlocked'
                handler(response)
            }

            // 发起请求
            const request: { [key: string]: Function } = {
                get: () => {
                    axios.get(url, { params }).then(callback)
                },
                post: () => {
                    axios.post(url, params).then(callback)
                },
                delete: () => {
                    axios.delete(url, { params }).then(callback)
                },
                put: () => {
                    axios.put(url, { params }).then(callback)
                }
            }

            // 判断当前的请求是否未锁
            if (ctx[moduleName][requestName].state === 'unlocked') {
                // 开始请求,将当前接口锁住
                ctx[moduleName][requestName].state = 'locked'

                if (request[method]) {
                    request[method]()
                } else {
                    reject(new Error('无效的请求类型'))
                }
            }
        })
    }
}

export default new AxiosServer()

4、配置请求

public模块的配置

// public模块的请求配置
const apis: IRequestConfig = {
    login: { url: '/api/public/login', method: 'post' },
    logout: { url: '/api/public/logout', method: 'delete' }
}

export default apis

business模块的配置

const apis: IHttpUrlConfig = {
    notes: { url: '/api/business/notes', method: 'get' }
}

export default apis

5、设置配置项

// 导入二次封装的AxiosServer实例
import server from '../utils/axios'
// 导入配置
import pub from './public'
import business from './business'

server.setOptions('public', pub)
server.setOptions('business', business)

export default server


// 最终的使用方式是 在需要请求的页面中 导入server
// 请求案例
// api就是导出的server
import api from './server'
api.public.login()
api.public.logout()
api.business.notes()

// 传参的请求方式
api.public.login({ data: { usercode: 'admin', userpwd: '123' }})

// 自定义处理请求的handler
api.business.notes({ handler: (response)=>{
    console.log(response)
}})

// 返回结果类型传入
interfance INote {
    note_id: number,
    note_content: string
}
api.business.notes<INote[]>()

三、结语

以上就是关于axios二次封装最简单的应用,防止短时间内同一个请求未响应,再次发起请求,这只是简单思路,如有不正确的地方,请及时指正。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浅墨、离殇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值