封装uniapp请求库

·  阅读 1324

基于uni.request(OBJECT)Promiseclass来封装一个通用、灵活可配置的、支持请求拦截和响应拦截的请求库。

第一步 声明创建Request类

我们首先定义一个名为Request的类。

class Request {
    /**
    * 内部的属性定义有:基础配置(config)、拦截器(interceptor)、请求方法表达式(get post put delete)
    */
    constructor(){
    
    }
    /**
    * 深度合并request对象实例的其他自定义请求参数
    */
    setConfig(){
    
    }
    /**
    * 主要请求部分,使用uni.request进行请求,并实现请求和响应的拦截
    */
    request(){
        
    }
}
export default new Request
复制代码

第二步 声明config属性

在constructor函数中,config对象内的属性设置了一些默认值。

constructor(){
    this.config = {
        baseUrl: '', // 请求的根域名
        header: {}, // 默认的请求头
        method: 'POST',
        dataType: 'json',// 设置为json,返回后uni.request会对数据进行一次JSON.parse
        responseType: 'text',// 此参数无需处理,因为5+和支付宝小程序不支持,默认为text即可
        showLoading: true, // 是否显示请求中的loading
        loadingText: '请求中...',
        loadingTime: 800, // 在此时间内,请求还没回来的话,就显示加载中动画,单位ms
        timer: null, // 定时器
        loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透
    }
    
    /**
     * 包含了值都为空的请求拦截和响应拦截属性的拦截器对象。
     */ 
    this.interceptor = {
        // 请求拦截
        request(config){
            config.data  = config.data || {}
            return config
        },
        // 响应拦截
        response(response){
           if (response.status !== 200) {
               uni.showToast({
                    icon:'none',
                    title:response.msg || '系统错误'
		})
		return Promise.reject(response)
           }
           return response.data || {}
        }
    }
    
    /**
     * 声明请求函数表达式:get post put delete。this.request方法在第四步声明
     */ 
    // get请求
    this.get = (url, data = {}, header = {}) => {
        return this.request({
            method: 'GET',
            url,
            header,
            data
        })
    }

    // post请求
    this.post = (url, data = {}, header = {}) => {
        return this.request({
            url,
            method: 'POST',
            header,
            data
        })
    }

    // put请求,不支持支付宝小程序
    this.put = (url, data = {}, header = {}) => {
        return this.request({
            url,
            method: 'PUT',
            header,
            data
        })
    }

    // delete请求,不支持支付宝和头条小程序
    this.delete = (url, data = {}, header = {}) => {
        return this.request({
            url,
            method: 'DELETE',
            header,
            data
        })
    }
}
复制代码

第三步 配置setConfig函数

    //判断是否是数组
    function isArray(obj){
        return Object.prototype.toString.call(obj) === '[object Array]'
    }
    
    //js 深度克隆
    function deepClone(obj){
        if([null, undefined, NaN, false].includes(obj) return obj;
        if(typeof obj !== 'function' && typeof obj !== 'object') return obj;
        var res = isArray(obj)? []: {};
        for(var i in obj){
            if(Object.prototype.hasOwnProperty.call(obj, i)){
                res[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
            }
        }
        return res
    }
    //js 深度合并
    function deepMerge(target = {}, source = {}) {
        target = deepClone(target);
        if (typeof target !== 'object' || typeof source !== 'object') return false;
        for (var prop in source) {
            if (!source.hasOwnProperty(prop)) continue;
            if (prop in target) {
                if (typeof target[prop] !== 'object') {
                    target[prop] = source[prop];
                }else{
                    if (typeof source[prop] !== 'object') {
                        target[prop] = source[prop];
                    }else{
                        if (target[prop].concat && source[prop].concat) {
                            target[prop] = target[prop].concat(source[prop]);
                        }else{
                            target[prop] = deepMerge(target[prop], source[prop]);
                        }
                    }
                }
            }else{
                target[prop] = source[prop];
            }
        }
        return target;
    }
       
    /**
     * setConfig接收一个自定义的配置对象,将类中的config对象和它进行深度合并。
     * @param {Object} customConfig  深度合并对象,否则会造成对象深层属性丢失
     */ 
    setConfig(customConfig) {
        this.config = deepMerge(this.config, customConfig);
    }
复制代码

第四步 主要的request部分

request (options = {}) {
    //检查请求拦截
    this.options = this.interceptor.request(options);
    options.dataType = options.dataType || this.config.dataType;
    options.responseType = options.responseType || this.config.responseType;
    options.url = options.url || '';
    options.params = options.params || {};
    options.header = Object.assign({}, this.config.header, options.header);
    options.method = options.method || this.config.method;
    
    return new Promise((resolve, reject) => {
        options.complete = (response) => {
            //请求返回后,隐藏loading
            uni.hideLoading();
            //清除定时器,如果请求快,不用显示loading
            clearTimeout(this.config.timer);
            this.config.timer = null;
             //响应拦截
            let resInterceptors = this.interceptor.response(response);
            resolve(resInterceptors);
        }
        //是否显示loading,加一个是否有已经有了timer的判断,否则两个同时请求的时候,后者会清除前者的定时器id,而没有清除前者的定时器,导致前者超时,一直显示loading
        if(this.config.showLoading && this.config.timer) {
            this.config.timer = setTimeout(()=>{
                uni.showLoading({
                    title: this.config.loadingText,
                    mask: this.config.loadingMask
                })
            },this.config.loadingTime)
        }
        uni.request(options)
    }
}
复制代码

第五步 创建config.js配置文件

该文件是给 request实例中的setConfig的参数。以下只写了baseUrl,如有需要还可以写上其他的基础配置项,比如methods,header等。

module.exports = {
    baseUrl: process.env.NODE_ENV === 'development' ? 'http://demo.com/' : 'https://demo.com/'
}

复制代码

第六步 生成实例对象http

引入以上创建的request类和config.js文件,创建request的实例对象http。

import config from '@/config.js'
import http from '@/request.js'
//调用setConfig对请求配置进行合并
const defaultConfig = {
    baseUrl: config.baseUrl
}
http.setConfig(defaultConfig)

export default http
复制代码

第七步 创建api.js接口文件

import http from '@/http.js'
export const getCouponsIndex = (params) => http.get('coupons',params)
export const setCouponReceive = (params) => http.post('coupon/receive',params)
复制代码

第八步 在页面引入接口文件

import {getCouponsIndex, setCouponReceive} from "@/api.js"
methods: {
    diyData() {
        let that = this;
        getCouponsIndex().then(res => {
              //接口成功返回的数据处理
        }).catch(err => {
              //接口失败返回的数据处理
        })
    },
}
复制代码
分类:
前端
标签:
分类:
前端
标签:
收藏成功!
已添加到「」, 点击更改