兼兼街公众号代码
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

280 lines
7.1 KiB

  1. import {
  2. API_URL
  3. } from '@/env'
  4. export default class Request {
  5. config = {
  6. baseUrl: API_URL,
  7. header: {
  8. 'content-type': 'application/x-www-form-urlencoded',
  9. 'platform': uni.getStorageSync('platform'),
  10. },
  11. method: 'GET',
  12. dataType: 'json',
  13. // #ifndef MP-ALIPAY || APP-PLUS
  14. responseType: 'text',
  15. // #endif
  16. custom: {},
  17. // #ifdef MP-ALIPAY
  18. timeout: 30000,
  19. // #endif
  20. // #ifdef APP-PLUS
  21. sslVerify: true
  22. // #endif
  23. }
  24. static posUrl(url) { /* 判断url是否为绝对路径 */
  25. return /(http|https):\/\/([\w.]+\/?)\S*/.test(url)
  26. }
  27. static addQueryString(params) {
  28. let paramsData = ''
  29. Object.keys(params).forEach(function(key) {
  30. paramsData += key + '=' + encodeURIComponent(params[key]) + '&'
  31. })
  32. return paramsData.substring(0, paramsData.length - 1)
  33. }
  34. /**
  35. * @property {Function} request 请求拦截器
  36. * @property {Function} response 响应拦截器
  37. * @type {{request: Request.interceptor.request, response: Request.interceptor.response}}
  38. */
  39. interceptor = {
  40. /**
  41. * @param {Request~requestCallback} cb - 请求之前拦截,接收一个函数config, cancel=> {return config}第一个参数为全局config,第二个参数为函数调用则取消本次请求
  42. */
  43. request: (cb) => {
  44. if (cb) {
  45. this.requestBeforeFun = cb
  46. }
  47. },
  48. /**
  49. * @param {Request~responseCallback} cb 响应拦截器对响应数据做点什么
  50. * @param {Request~responseErrCallback} ecb 响应拦截器对响应错误做点什么
  51. */
  52. response: (cb, ecb) => {
  53. if (cb && ecb) {
  54. this.requestComFun = cb
  55. this.requestComFail = ecb
  56. }
  57. }
  58. }
  59. requestBeforeFun(config) {
  60. return config
  61. }
  62. requestComFun(response) {
  63. return response
  64. }
  65. requestComFail(response) {
  66. return response
  67. }
  68. /**
  69. * 自定义验证器如果返回true 则进入响应拦截器的响应成功函数(resolve)否则进入响应拦截器的响应错误函数(reject)
  70. * @param { Number } statusCode - 请求响应体statusCode只读
  71. * @return { Boolean } 如果为true, resolve, 否则 reject
  72. */
  73. validateStatus(statusCode) {
  74. return statusCode === 200
  75. }
  76. /**
  77. * @Function
  78. * @param {Request~setConfigCallback} f - 设置全局默认配置
  79. */
  80. setConfig(f) {
  81. this.config = f(this.config)
  82. }
  83. /**
  84. * @Function
  85. * @param {Object} options - 请求配置项
  86. * @prop {String} options.url - 请求路径
  87. * @prop {Object} options.data - 请求参数
  88. * @prop {Object} [options.responseType = config.responseType] [text|arraybuffer] - 响应的数据类型
  89. * @prop {Object} [options.dataType = config.dataType] - 如果设为 json会尝试对返回的数据做一次 JSON.parse
  90. * @prop {Object} [options.header = config.header] - 请求header
  91. * @prop {Object} [options.method = config.method] - 请求方法
  92. * @returns {Promise<unknown>}
  93. */
  94. async request(options = {}) {
  95. options.baseUrl = this.config.baseUrl
  96. options.dataType = options.dataType || this.config.dataType
  97. // #ifndef MP-ALIPAY || APP-PLUS
  98. options.responseType = options.responseType || this.config.responseType
  99. // #endif
  100. // #ifdef MP-ALIPAY
  101. options.timeout = options.timeout || this.config.timeout
  102. // #endif
  103. options.url = options.url || ''
  104. options.data = options.data || {}
  105. options.params = options.params || {}
  106. options.header = options.header || this.config.header
  107. options.method = options.method || this.config.method
  108. options.custom = { ...this.config.custom,
  109. ...(options.custom || {})
  110. }
  111. // #ifdef APP-PLUS
  112. options.sslVerify = options.sslVerify === undefined ? this.config.sslVerify : options.sslVerify
  113. // #endif
  114. // uni.showToast({
  115. // icon: "loading",
  116. // image: "/static/imgs//logo/logo.gif"
  117. // })
  118. return new Promise((resolve, reject) => {
  119. let next = true
  120. let handleRe = {}
  121. options.complete = (response) => {
  122. response.config = handleRe
  123. if (this.validateStatus(response.statusCode)) { // 成功
  124. response = this.requestComFun(response)
  125. resolve(response.data)
  126. } else if (401 === response.statusCode) {
  127. response = this.requestComFun(response)
  128. resolve(response.data)
  129. } else if (500 === response.statusCode) {
  130. resolve(response.data)
  131. } else {
  132. response = this.requestComFail(response)
  133. reject(response)
  134. }
  135. }
  136. const cancel = (t = 'handle cancel', config = options) => {
  137. const err = {
  138. errMsg: t,
  139. config: config
  140. }
  141. reject(err)
  142. next = false
  143. }
  144. handleRe = { ...this.requestBeforeFun(options, cancel)
  145. }
  146. const _config = { ...handleRe
  147. }
  148. if (!next) return
  149. delete _config.custom
  150. let mergeUrl = Request.posUrl(_config.url) ? _config.url : (_config.baseUrl + _config.url)
  151. if (JSON.stringify(_config.params) !== '{}') {
  152. const paramsH = Request.addQueryString(_config.params);
  153. mergeUrl += mergeUrl.indexOf('?') === -1 ? `?${paramsH}` : `&${paramsH}`
  154. }
  155. _config.url = mergeUrl
  156. uni.request(_config)
  157. })
  158. }
  159. get(url, options = {}) {
  160. return this.request({
  161. url,
  162. method: 'GET',
  163. ...options
  164. })
  165. }
  166. post(url, data, options = {}) {
  167. return this.request({
  168. url,
  169. data,
  170. method: 'POST',
  171. ...options
  172. })
  173. }
  174. upload(url, {
  175. // #ifdef APP-PLUS
  176. files,
  177. // #endif
  178. // #ifdef MP-ALIPAY
  179. fileType,
  180. // #endif
  181. filePath,
  182. name,
  183. header,
  184. formData,
  185. custom
  186. }) {
  187. return new Promise((resolve, reject) => {
  188. let next = true
  189. let handleRe = {}
  190. const globalHeader = { ...this.config.header
  191. }
  192. delete globalHeader['content-type']
  193. const pubConfig = {
  194. baseUrl: this.config.baseUrl,
  195. url,
  196. // #ifdef APP-PLUS
  197. files,
  198. // #endif
  199. // #ifdef MP-ALIPAY
  200. fileType,
  201. // #endif
  202. filePath,
  203. method: 'UPLOAD',
  204. name,
  205. header: header || globalHeader,
  206. formData,
  207. custom: { ...this.config.custom,
  208. ...(custom || {})
  209. },
  210. complete: (response) => {
  211. response.config = handleRe
  212. if (response.statusCode === 200) { // 成功
  213. response = this.requestComFun(response)
  214. resolve(response)
  215. } else {
  216. response = this.requestComFail(response)
  217. reject(response)
  218. }
  219. }
  220. }
  221. const cancel = (t = 'handle cancel', config = pubConfig) => {
  222. const err = {
  223. errMsg: t,
  224. config: config
  225. }
  226. reject(err)
  227. next = false
  228. }
  229. handleRe = { ...this.requestBeforeFun(pubConfig, cancel)
  230. }
  231. const _config = { ...handleRe
  232. }
  233. if (!next) return
  234. delete _config.custom
  235. _config.url = Request.posUrl(_config.url) ? _config.url : (_config.baseUrl + _config.url)
  236. uni.uploadFile(_config)
  237. })
  238. }
  239. }
  240. /**
  241. * setConfig回调
  242. * @return {Object} - 返回操作后的config
  243. * @callback Request~setConfigCallback
  244. * @param {Object} config - 全局默认config
  245. */
  246. /**
  247. * 请求拦截器回调
  248. * @return {Object} - 返回操作后的config
  249. * @callback Request~requestCallback
  250. * @param {Object} config - 全局config
  251. * @param {Function} [cancel] - 取消请求钩子调用会取消本次请求
  252. */
  253. /**
  254. * 响应拦截器回调
  255. * @return {Object} - 返回操作后的response
  256. * @callback Request~responseCallback
  257. * @param {Object} response - 请求结果 response
  258. */
  259. /**
  260. * 响应错误拦截器回调
  261. * @return {Object} - 返回操作后的response
  262. * @callback Request~responseErrCallback
  263. * @param {Object} response - 请求结果 response
  264. */