index.js 8.2 KB

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