index.js 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  1. class WxRequest {
  2. // 定义实例属性,用来设置默认请求参数
  3. defaults = {
  4. baseURL: '', // 请求基准地址
  5. url: '', // 接口的请求路径
  6. data: null, // 请求参数
  7. method: 'GET', // 默认的请求方法
  8. // 请求头
  9. header: {
  10. 'Content-type': 'application/json' // 设置数据的交互格式
  11. },
  12. timeout: 60000, // 默认的超时时长,小程序默认的超时时长是 1 分钟
  13. isLoading: true // 控制是否使用默认的 loading,默认值是 true 表示使用默认的 loading
  14. }
  15. // 定义拦截器对象
  16. interceptors = {
  17. // 请求拦截器
  18. request: (config) => config,
  19. // 响应拦截器
  20. response: (response) => response
  21. }
  22. // 定义数组队列,用来存储请求队列、存储请求标识
  23. queue = []
  24. // constructor 用于创建和初始化类的属性以及方法
  25. constructor(params = {}) {
  26. // 注意:需要传入的参数,覆盖默认的参数,因此传入的参数需要放到最后
  27. this.defaults = Object.assign({}, this.defaults, params)
  28. }
  29. /**
  30. * @description request 实例方法发送网络请求,接收一个对象类型的参数
  31. * @param {*} options 属性值和 wx.request() 方法调用时传递的参数保持一致
  32. * @returns Promise
  33. */
  34. request(options) {
  35. // 如果有新的请求,就清除上一次的定时器
  36. this.timerId && clearTimeout(this.timerId)
  37. // 合并完整的请求地址
  38. options.url = this.defaults.baseURL + options.url
  39. // 合并请求参数:调用实例方法时传入的覆盖默认的以及实例配置的
  40. options = {
  41. ...this.defaults,
  42. ...options
  43. }
  44. // 控制 loading 的显示与隐藏
  45. if (options.isLoading) {
  46. this.queue.length === 0 && wx.showLoading({
  47. mask: true
  48. })
  49. this.queue.push('request')
  50. }
  51. // 在请求发送之前,调用请求拦截器,新增和修改请求参数
  52. // 请求拦截器内部,会将新增和修改以后的参数返回
  53. options = this.interceptors.request(options)
  54. // 需要使用 Promise 封装 wx.request,处理异步请求
  55. return new Promise((resolve, reject) => {
  56. // 如果 method 等于 UPLOAD 说明需要调用 wx.uploadFile() 方法
  57. // 否则调用的是 wx.request() 方法
  58. if (options.method === 'UPLOAD') {
  59. wx.uploadFile({
  60. ...options,
  61. success: (res) => {
  62. // 需要将服务器返回的 JSON 字符串 通过 JSON.parse 转成对象
  63. res.data = JSON.parse(res.data)
  64. // 合并参数
  65. const mergeRes = Object.assign({}, res, {
  66. config: options,
  67. isSuccess: true
  68. })
  69. resolve(this.interceptors.response(mergeRes, options))
  70. },
  71. fail: (err) => {
  72. // 合并参数
  73. const mergeErr = Object.assign({}, err, {
  74. config: options,
  75. isSuccess: false
  76. })
  77. reject(this.interceptors.response(mergeErr, options))
  78. },
  79. // 接口调用结束的回调函数(调用成功、失败都会执行)
  80. complete: () => {
  81. // 如果需要显示 loading ,那么就需要控制 loading 的隐藏
  82. if (options.isLoading) {
  83. // 在每一个请求结束以后,都会执行 complete 回调函数
  84. // 每次从 queue 队列中删除一个标识
  85. this.queue.pop()
  86. // 解决并发请求,loading 闪烁问题
  87. this.queue.length === 0 && this.queue.push('request')
  88. //解决并发请求,loading 闪烁问题
  89. this.timerId = setTimeout(() => {
  90. this.queue.pop()
  91. this.queue.length === 0 && wx.hideLoading()
  92. clearTimeout(this.timerId)
  93. }, 1)
  94. }
  95. }
  96. })
  97. } else {
  98. //console.log(options.url)
  99. wx.request({
  100. ...options,
  101. // 当接口调用成功时会触发 success 回调函数
  102. success: (res) => {
  103. // 合并请求参数,方便进行代码调试
  104. // 追加 isSuccess 属性,是为了标识响应拦截器是 success 调用还是 fail 调用
  105. const mergeRes = Object.assign({}, res, {
  106. config: options,
  107. isSuccess: true
  108. })
  109. resolve(this.interceptors.response(mergeRes, options))
  110. },
  111. // 当接口调用失败时会触发 fail 回调函数
  112. fail: (err) => {
  113. // 合并请求参数,方便进行代码调试
  114. // 追加 isSuccess 属性,是为了标识响应拦截器是 success 调用还是 fail 调用
  115. const mergeErr = Object.assign({}, err, {
  116. config: options,
  117. isSuccess: false
  118. })
  119. reject(this.interceptors.response(mergeErr, options))
  120. },
  121. // 接口调用结束的回调函数(调用成功、失败都会执行)
  122. complete: () => {
  123. // 如果需要显示 loading ,那么就需要控制 loading 的隐藏
  124. if (options.isLoading) {
  125. // 在每一个请求结束以后,都会执行 complete 回调函数
  126. // 每次从 queue 队列中删除一个标识
  127. this.queue.pop()
  128. // 解决并发请求,loading 闪烁问题
  129. this.queue.length === 0 && this.queue.push('request')
  130. //解决并发请求,loading 闪烁问题
  131. this.timerId = setTimeout(() => {
  132. this.queue.pop()
  133. this.queue.length === 0 && wx.hideLoading()
  134. clearTimeout(this.timerId)
  135. }, 1)
  136. }
  137. }
  138. })
  139. }
  140. })
  141. }
  142. /**
  143. * @description 封装 GET 实例方法
  144. * @param {*} url 请求地址
  145. * @param {*} data 请求参数
  146. * @param {*} config 其他请求配置项
  147. * @returns Promise
  148. */
  149. get(url, data = {}, config = {}) {
  150. // 需要调用 request 请求方法发送请求,只需要组织好参数,传递给 request 请求方法即可
  151. // 当调用 get 方法时,需要将 request 方法的返回值 return 出去
  152. return this.request(Object.assign({
  153. url,
  154. data,
  155. method: 'GET'
  156. }, config))
  157. }
  158. /**
  159. * @description 封装 DELETE 实例方法
  160. * @param {*} url 请求地址
  161. * @param {*} data 请求参数
  162. * @param {*} config 其他请求配置项
  163. * @returns Promise
  164. */
  165. delete(url, data = {}, config = {}) {
  166. return this.request(Object.assign({
  167. url,
  168. data,
  169. method: 'DELETE'
  170. }, config))
  171. }
  172. /**
  173. * @description 封装 POST 实例方法
  174. * @param {*} url 请求地址
  175. * @param {*} data 请求参数
  176. * @param {*} config 其他请求配置项
  177. * @returns Promise
  178. */
  179. post(url, data = {}, config = {}) {
  180. return this.request(Object.assign({
  181. url,
  182. data,
  183. method: 'POST'
  184. }, config))
  185. }
  186. /**
  187. * @description 封封装 PUT 实例方法
  188. * @param {*} url 请求地址
  189. * @param {*} data 请求参数
  190. * @param {*} config 其他请求配置项
  191. * @returns Promise
  192. */
  193. put(url, data = {}, config = {}) {
  194. return this.request(Object.assign({
  195. url,
  196. data,
  197. method: 'PUT'
  198. }, config))
  199. }
  200. /**
  201. * @description 处理并发请求
  202. * @param {...promise} promise 传入的每一项需要是 Promise
  203. * @returns Promise
  204. */
  205. all(...promise) {
  206. // 那么展开运算符会将传入的参数转成数组
  207. return Promise.all(promise)
  208. }
  209. /**
  210. * @description upload 实例方法,用来对 wx.uploadFile 进行封装
  211. * @param {*} url 文件的上传地址、接口地址
  212. * @param {*} filePath 要上传的文件资源路径
  213. * @param {*} name 文件对应的 key
  214. * @param {*} config 其他配置项
  215. */
  216. upload(url, filePath, name = 'file', config = {}) {
  217. return this.request(
  218. Object.assign({
  219. url,
  220. filePath,
  221. name,
  222. method: 'UPLOAD'
  223. }, config)
  224. )
  225. }
  226. }
  227. export default WxRequest