如何高效封装一个http请求

146 阅读2分钟

如何高效封装一个网络请求

高效封装网络请求需要考虑以下几点

1.  单例模式

class Http {
    constructor(){
        this.instance = ''
        ....
    }
    static getInstance(){
        return this.instance || new Http()
    }
}

export default Http.getInstance()

2.  封装网络请求对象

包括请求方法、请求参数、请求头、URL等信息

class Http {
    constructor(){
        this.instance = ''
        this.config = {...}
        ....
    }
    
    get(options){
        const {data, params } = options
        const _data = data || params || {}
        return this._request({
            ...options,
            url: this.handleURL({ ...options, method: 'GET', data: _data }),
            data: data || params || {},
            method: 'GET',
        }).then((res: IResponseData) => {
            ...
        }).catch((err = {}) => {
            ...
        })
     }

    // 处理url,拼接时间戳,get,post的参数

    handleURL(options){
    }
    
    //处理公共的头部
    _request(options){
        const { header} = this.config
        const requestTask = Request.request({
            ...options,
            data: JSON.stringify(data)
            header: {
            ...header,
            ...options.header
            }
            success:()=>{}
            fail: ()=>{}
        })
    }
    
    post(options){
        ...
    }

    static getInstance(){
        return this.instance || new Http()
    }
}

export default Http.getInstance()

3.  封装网络请求结果回调,

包括请求成功、请求失败、错误等结果回调方法

class Http {
    constructor(){
        this.instance = ''
        this.config = {...}
        this.hook = {
            requestBefore, // 处理userkey,设置header
            requestComplete, // 处理401未登录的情况,处理usekey的更新
        }
        ....
    }

    get(options){
        const {data, params } = options
        const _data = data || params || {}
        this._callHookFun('requestBefore', options)
        return this._request({
            ...options,
            url: this.handleURL({ ...options, method: 'GET', data: _data }),
            data: data || params || {},
            method: 'GET',
        }).then((res: IResponseData) => {
            this._callHookFun('requestComplete', res)
            ...
        }).catch((err = {}) => {
            this._callHookFun('requestError', err)
            ...
        })
    }

    // 处理hook调用

    _callHookFun(hookName: 'requestBefore' | 'requestComplete' | 'requestError' ) {
        if (typeof this.hook[hookName] === 'function') {
            (this.hook[hookName] as Function)(options)
        }
    }
    
    // 处理url,拼接时间戳,get,post的参数
    handleURL(options){

    }

    // 处理公共的头部,封装请求
    _request(options){
        const { header} = this.config
        const requestTask = Request.request({
            ...options,
            data: JSON.stringify(data)
            header: {
                ...header,
                ...options.header
            }
            success:()=>{}
            fail: ()=>{}
        })
    }

    static getInstance(){
        return this.instance || new Http()
    }
}

export default Http.getInstance()

4.  网络请求的并发处理

Request.request,对上边request方法进行扩展(简化版),并发处理5条网络请求

class RequestQueue {
    constructor() {
        this.queue = []
        this.timer = 0,
        this.limitNum = 5
    }

    request(options) {
        this.queue.push(options)
        return this.run() // 需要有返回值
    }
    
    run() {
        if (!this.queue.length) {
            return null
        }
        if (this.queue.length <= this.limitNum) {
            const options = this.queue.pop()
            const completeFn = options.complete
            options.complete = (...args) => {
            completeFn && completeFn.apply(options, args)
            this.run()
        }
        return wx.request(options)
    }
    static getInstance() {
        return this.instance || new RequestQueue()
    }
}

export default RequestQueue.getInstance()

5. 网络请求的缓存处理

cacheDate //缓存时间

async function get(options){
    return cacheLoad(()=>{
        ....
        return Http.get().then(()=>{})
    })
}

// 处理缓存请求的存取
function cacheLoad(req){
    。。。
}

6.  网络异常的处理

    async function get(options){
        return cacheLoad(()=>checkNetwork(()=>{
            ....
            return Http.get().then(()=>{})
        })
        })
     }

    export function checkNetwork(callback, options) {
        const { networkInfo = {} } = getApp().globalData
        if (networkInfo === true || networkInfo.isConnected) {
            return callback()
        }
        toast(!!options.hideToast, '网络异常,请重试')
        return Promise.reject({ message: '网络异常,请重试' })

    }

7.  撤销怎么设计

abortKey的设计

    // 以上_request方法的扩展

    _request(options,abortKey){
        const { header} = this.config
        const requestTask = Request.request({
            ...options,
            data: JSON.stringify(data)
            header: {
                ...header,
                ...options.header
            }
            success:()=>{}
            fail: ()=>{}
        })
        abortKey && this._abortRequest(abortKey, requestTask)
    }

    // @params requestTask是网络请求的id

    _abortRequest(abortKey: string, requestTask: any) {
        if (abortKey) {
            const task = this.requestTask[abortKey]
            task && task.abort()
            this.requestTask[abortKey] = requestTask
        }
    }

8.  网络请求的重试。。。