请求模块封装(带请求拦截器和响应拦截器)

前言

今天写小程序,微信的原生的请求模块使用起来非常麻烦,所以就想着自己封装一个类似于axios的功能,本代码直接使用的es6规范,如果要适应浏览器,请自行转换

我先说一下执行流程

调用get或者post方法开始执行请求流程
-》 对传入的url和config和data等参数进行处理
-》 进入请求拦截器(Y)
-》 发起网络请求
-》进入响应拦截器 (Y)
-》 返回响应结果

就这么简单,这是我个人对axios的基本理解,如果有错误还请指正

代码

废话不多说,直接上代码

class Request {
    //默认的配置项
    config = {
        baseUrl: "",
        header: {},
    }
    //所有允许的返回状态码,不在其中的都会报错
    statusCodes = /^2\d\d$/

    constructor(config = {}) {
        this.config = config
    }

    //外部设置BaseUrl,对其进行规范处理(结尾不带/)
    set baseUrl(BaseUrl) {
        BaseUrl = BaseUrl || BaseUrl + ''
        if (/https?:\/\//.test(BaseUrl)) {
            this.config.baseUrl = BaseUrl.endsWith("/") ? BaseUrl.slice(0, -1) : BaseUrl
        }
        this.config.baseUrl = BaseUrl || ""
    }

    //外部获取BaseUrl
    get baseUrl() {
        return this.config.baseUrl;
    }

    isFussCode(statusCode) {
        return this.statusCodes.test(statusCode)
    }

    //格式化URL
    FormatUrl(url) {
        let isUrl = /https?:\/\//.test(url)
        if (!isUrl) {
            return url.startsWith("/") ? (this.baseUrl + url) : (this.baseUrl + "/" + url)
        }
        return url
    }

    //请求方法(私有,禁止外部调用此方法,因为此方法不会经过拦截器)
    #req = (method, url, params, config) => {
        const that = this;
        return new Promise((resolve, reject) => {
            //对应各种平台的原生网络模块即可适应各种平台
            uni.request({
                method,
                url,
                data: params,
                header: config.header,
                success: (res) => {
                //判断状态码是非在允许范围内
                    if (that.isFussCode(res.statusCode)) {
                        resolve(res)
                    } else {
                        reject(new Error(`Request Waring:  Response statusCodes: ${res.statusCode} is not in operation. You can provide statusCodes that modify the Request to define permissible statusCodes, such as /^2\\d\\d$/`))
                    }
                },
                fail: (err) => {
                    reject(err)
                }
            })
        })
    }
    //下面是两个拦截器的默认值

    /**
     * 请求拦截器
     * 接收4个参数:config, params, url, method
     * 返回一个config作为新的config
     * 如果要中断流程,返回一个reject或者抛出一个错误即可
     * */
    requestIntercept = function (config, params, url, method) {
        return config
    }

    /**
     * 响应拦截器
     * 返回response
     * 如果要中断流程,返回一个reject或者抛出一个错误即可
     * */
    responseIntercept = function (response) {
        return response
    }

    //按流程请求,私有方法,为了防止外部修改,因为其他方法依赖此方法
    #request = async (configs) => {
        let {config, params, url, method} = configs
        //请求拦截器,获取到新的config
        config = await this.requestIntercept(config, params, url, method)
        //请求发送
        let response = await this.#req(method, url, params, config)
        //响应拦截器
        return await this.responseIntercept(response)
    }

    //合并Object,约往后级别越高
    mergeObject(obj1, obj2) {
        obj1 = JSON.parse(JSON.stringify(obj1))
        for (const requestKey in obj2) {
            if (obj1.hasOwnProperty(requestKey)) {//两个对象都含有该属性
                if (typeof obj2[requestKey] === "object") {
                    obj1[requestKey] = fun01(obj1[requestKey], obj2[requestKey])
                } else {
                    obj1[requestKey] = obj2[requestKey]
                }
            } else {
                obj1[requestKey] = obj2[requestKey]
            }
        }
        return obj1
    }

    //发送一个GET请求
    async get(url, params, config) {
        return await this.#request({
            params,
            url: this.FormatUrl(url),
            config: this.mergeObject(this.config, config),
            method: "GET"
        })
    }

    //发送一个POST请求
    async post(url, params, config) {
        return await this.#request({
            params,
            url: this.FormatUrl(url),
            config: this.mergeObject(this.config, config),
            method: "POST"
        })
    }
}

export default Request

一个Api例子

import Request from "../Util/Request";

const request = new Request({
    baseUrl: "http://127.0.0.1:10086/"
})

//...
export const getOpenId = params => request.post("https://www.baidu.com/", params)
//...

希望我的代码对你有一点帮助
最后,开来加入QQ群一起讨论技术吧,里面各种大牛等着你喔。我们非常乐意为萌新们解决问题,更加乐意与大神们讨论技术,一起成长。qq群: 365399843

  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值