guangchao.xu | 070005a | 2020-12-07 09:56:40 +0800 | [diff] [blame] | 1 | import deepMerge from "../function/deepMerge"; |
| 2 | import validate from "../function/test"; |
| 3 | class Request { |
| 4 | // 设置全局默认配置 |
| 5 | setConfig(customConfig) { |
| 6 | // 深度合并对象,否则会造成对象深层属性丢失 |
| 7 | this.config = deepMerge(this.config, customConfig); |
| 8 | } |
| 9 | |
| 10 | // 主要请求部分 |
| 11 | request(options = {}) { |
| 12 | // 检查请求拦截 |
| 13 | if (this.interceptor.request && typeof this.interceptor.request === 'function') { |
| 14 | let tmpConfig = {}; |
| 15 | let interceptorRequest = this.interceptor.request(options); |
| 16 | if (interceptorRequest === false) { |
| 17 | // 返回一个处于pending状态中的Promise,来取消原promise,避免进入then()回调 |
| 18 | return new Promise(()=>{}); |
| 19 | } |
| 20 | this.options = interceptorRequest; |
| 21 | } |
| 22 | options.dataType = options.dataType || this.config.dataType; |
| 23 | options.responseType = options.responseType || this.config.responseType; |
| 24 | options.url = options.url || ''; |
| 25 | options.params = options.params || {}; |
| 26 | options.header = Object.assign(this.config.header, options.header); |
| 27 | options.method = options.method || this.config.method; |
| 28 | |
| 29 | return new Promise((resolve, reject) => { |
| 30 | options.complete = (response) => { |
| 31 | // 请求返回后,隐藏loading(如果请求返回快的话,可能会没有loading) |
| 32 | uni.hideLoading(); |
| 33 | // 清除定时器,如果请求回来了,就无需loading |
| 34 | clearTimeout(this.config.timer); |
| 35 | this.config.timer = null; |
| 36 | // 判断用户对拦截返回数据的要求,如果originalData为true,返回所有的数据(response)到拦截器,否则只返回response.data |
| 37 | if(this.config.originalData) { |
| 38 | // 判断是否存在拦截器 |
| 39 | if (this.interceptor.response && typeof this.interceptor.response === 'function') { |
| 40 | let resInterceptors = this.interceptor.response(response); |
| 41 | // 如果拦截器不返回false,就将拦截器返回的内容给this.$u.post的then回调 |
| 42 | if (resInterceptors !== false) { |
| 43 | resolve(resInterceptors); |
| 44 | } else { |
| 45 | // 如果拦截器返回false,意味着拦截器定义者认为返回有问题,直接接入catch回调 |
| 46 | reject(response); |
| 47 | } |
| 48 | } else { |
| 49 | // 如果要求返回原始数据,就算没有拦截器,也返回最原始的数据 |
| 50 | resolve(response); |
| 51 | } |
| 52 | } else { |
| 53 | if (response.statusCode == 200) { |
| 54 | if (this.interceptor.response && typeof this.interceptor.response === 'function') { |
| 55 | let resInterceptors = this.interceptor.response(response.data); |
| 56 | if (resInterceptors !== false) { |
| 57 | resolve(resInterceptors); |
| 58 | } else { |
| 59 | reject(response.data); |
| 60 | } |
| 61 | } else { |
| 62 | // 如果不是返回原始数据(originalData=false),且没有拦截器的情况下,返回纯数据给then回调 |
| 63 | resolve(response.data); |
| 64 | } |
| 65 | } else { |
| 66 | // 不返回原始数据的情况下,服务器状态码不为200,modal弹框提示 |
| 67 | // if(response.errMsg) { |
| 68 | // uni.showModal({ |
| 69 | // title: response.errMsg |
| 70 | // }); |
| 71 | // } |
| 72 | reject(response) |
| 73 | } |
| 74 | } |
| 75 | } |
| 76 | |
| 77 | // 判断用户传递的URL是否/开头,如果不是,加上/,这里使用了uView的test.js验证库的url()方法 |
| 78 | options.url = validate.url(options.url) ? options.url : (this.config.baseUrl + (options.url.indexOf('/') == 0 ? |
| 79 | options.url : '/' + options.url)); |
| 80 | |
| 81 | // 是否显示loading |
| 82 | // 加一个是否已有timer定时器的判断,否则有两个同时请求的时候,后者会清除前者的定时器id |
| 83 | // 而没有清除前者的定时器,导致前者超时,一直显示loading |
| 84 | if(this.config.showLoading && !this.config.timer) { |
| 85 | this.config.timer = setTimeout(() => { |
| 86 | uni.showLoading({ |
| 87 | title: this.config.loadingText, |
| 88 | mask: this.config.loadingMask |
| 89 | }) |
| 90 | this.config.timer = null; |
| 91 | }, this.config.loadingTime); |
| 92 | } |
| 93 | uni.request(options); |
| 94 | }) |
| 95 | // .catch(res => { |
| 96 | // // 如果返回reject(),不让其进入this.$u.post().then().catch()后面的catct() |
| 97 | // // 因为很多人都会忘了写后面的catch(),导致报错捕获不到catch |
| 98 | // return new Promise(()=>{}); |
| 99 | // }) |
| 100 | } |
| 101 | |
| 102 | constructor() { |
| 103 | this.config = { |
| 104 | baseUrl: '', // 请求的根域名 |
| 105 | // 默认的请求头 |
| 106 | header: {}, |
| 107 | method: 'POST', |
| 108 | // 设置为json,返回后uni.request会对数据进行一次JSON.parse |
| 109 | dataType: 'json', |
| 110 | // 此参数无需处理,因为5+和支付宝小程序不支持,默认为text即可 |
| 111 | responseType: 'text', |
| 112 | showLoading: true, // 是否显示请求中的loading |
| 113 | loadingText: '请求中...', |
| 114 | loadingTime: 800, // 在此时间内,请求还没回来的话,就显示加载中动画,单位ms |
| 115 | timer: null, // 定时器 |
| 116 | originalData: false, // 是否在拦截器中返回服务端的原始数据,见文档说明 |
| 117 | loadingMask: true, // 展示loading的时候,是否给一个透明的蒙层,防止触摸穿透 |
| 118 | } |
| 119 | |
| 120 | // 拦截器 |
| 121 | this.interceptor = { |
| 122 | // 请求前的拦截 |
| 123 | request: null, |
| 124 | // 请求后的拦截 |
| 125 | response: null |
| 126 | } |
| 127 | |
| 128 | // get请求 |
| 129 | this.get = (url, data = {}, header = {}) => { |
| 130 | return this.request({ |
| 131 | method: 'GET', |
| 132 | url, |
| 133 | header, |
| 134 | data |
| 135 | }) |
| 136 | } |
| 137 | |
| 138 | // post请求 |
| 139 | this.post = (url, data = {}, header = {}) => { |
| 140 | return this.request({ |
| 141 | url, |
| 142 | method: 'POST', |
| 143 | header, |
| 144 | data |
| 145 | }) |
| 146 | } |
| 147 | |
| 148 | // put请求,不支持支付宝小程序(HX2.6.15) |
| 149 | this.put = (url, data = {}, header = {}) => { |
| 150 | return this.request({ |
| 151 | url, |
| 152 | method: 'PUT', |
| 153 | header, |
| 154 | data |
| 155 | }) |
| 156 | } |
| 157 | |
| 158 | // delete请求,不支持支付宝和头条小程序(HX2.6.15) |
| 159 | this.delete = (url, data = {}, header = {}) => { |
| 160 | return this.request({ |
| 161 | url, |
| 162 | method: 'DELETE', |
| 163 | header, |
| 164 | data |
| 165 | }) |
| 166 | } |
| 167 | } |
| 168 | } |
| 169 | export default new Request |