request.js 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. export default function({
  2. baseURL,
  3. timeout = 56 * 1000,
  4. header: headers
  5. }) {
  6. return {
  7. get(url, data, header, ...args) {
  8. return this.request('GET', url, data, {
  9. ...headers,
  10. ...header
  11. }, ...args)
  12. },
  13. post(url, data, header, ...args) {
  14. return this.request('POST', url, data, {
  15. ...headers,
  16. ...header
  17. }, ...args)
  18. },
  19. put(url, data, header, ...args) {
  20. return this.request('PUT', url, data, {
  21. ...headers,
  22. ...header
  23. }, ...args)
  24. },
  25. delete(url, data, header, ...args) {
  26. return this.request('DELETE', url, data, {
  27. ...headers,
  28. ...header
  29. }, ...args)
  30. },
  31. connect(url, data, header, ...args) {
  32. return this.request('CONNECT', url, data, {
  33. ...headers,
  34. ...header
  35. }, ...args)
  36. },
  37. head(url, data, header, ...args) {
  38. return this.request('HEAD', url, data, {
  39. ...headers,
  40. ...header
  41. }, ...args)
  42. },
  43. options(url, data, header, ...args) {
  44. return this.request('OPTIONS', url, data, {
  45. ...headers,
  46. ...header
  47. }, ...args)
  48. },
  49. reace(url, data, header, ...args) {
  50. return this.request('TRACE', url, data, {
  51. ...headers,
  52. ...header
  53. }, ...args)
  54. },
  55. uploadFile(url, data, header, ...args) {
  56. return this.file('uploadFile', url, data || {}, {
  57. ...header,
  58. ...headers
  59. }, ...args)
  60. },
  61. downloadFile(url, data, header, ...args) {
  62. return this.file('downloadFile', url, data || {}, {
  63. ...header,
  64. ...headers
  65. }, ...args)
  66. },
  67. onerror: () => {}, // 请求错误钩子函数集合
  68. file(method, url, data, header, reqIntercept=true, resIntercept=true) {
  69. console.log(data);
  70. let timer, // timer 检测超时定时器
  71. requestTask, // requestTask 网络请求 task 对象
  72. aborted = false, // aborted 请求是否已被取消
  73. overtime = false, // overtime 请求是否超时
  74. abort = () => { // abort 取消请求方法
  75. aborted = true // 将请求状态标记为已取消
  76. requestTask ? requestTask.abort() : '' // 执行取消请求方法
  77. },
  78. progressUpdateHandle,
  79. onProgressUpdate = e => progressUpdateHandle =
  80. e // progressUpdateHandle 监听上传进度变化回调,onProgressUpdate 监听上传进度变化方法
  81. return new Proxy(new Promise((resolve,
  82. reject) => { // 返回经过 Proxy 后的 Promise 对象使其可以监听到是否调用 abort 和 onProgressUpdate 方法
  83. this.interceptors.request.intercept({
  84. header: header || {},
  85. body: data.formData || {}
  86. }, method, url, data, reqIntercept).then(async ({
  87. header,
  88. body,
  89. cancel
  90. }) => { // 等待请求拦截器里的方法执行完
  91. if (aborted || cancel) { // 如果请求已被取消,停止执行,返回 reject
  92. await this.onerror(method, url, data, '网络请求失败:主动取消')
  93. return reject('网络请求失败:主动取消')
  94. }
  95. console.log(body);
  96. requestTask = uni[method]({
  97. // url: url[0] === '/' ? baseURL + url : url,
  98. url: baseURL + url,
  99. name: data.name,
  100. header,
  101. filePath: data.filePath,
  102. formData: body,
  103. success: async res => {
  104. clearTimeout(timer)
  105. this.interceptors.response.intercept(resolve, {
  106. success: true,
  107. ...res,
  108. }, method, url, data, reject,
  109. resIntercept) // 执行响应拦截器
  110. },
  111. fail: async res => {
  112. clearTimeout(timer);
  113. !overtime && await this.onerror(
  114. method, url, data, aborted ? '网络请求失败:主动取消' :
  115. '网络请求失败:(URL无效|无网络|DNS解析失败)')
  116. aborted ? reject('网络请求失败:主动取消') : reject(
  117. '网络请求失败:(URL无效|无网络|DNS解析失败)')
  118. }
  119. })
  120. requestTask.onProgressUpdate(progressUpdateHandle) // 监听下载进度变化
  121. timer = setTimeout(async () => { // 请求超时执行方法
  122. overtime = true // 将状态标记为超时,不会被 fail 中的 onerror 重复执行
  123. requestTask.abort() // 执行取消请求方法
  124. await this.onerror(method, url, data, '网络请求失败:超时取消')
  125. reject('网络请求时间超时') // reject 原因
  126. }, timeout) // 设定检测超时定时器
  127. })
  128. }), {
  129. get: (target, prop) => {
  130. if (prop === 'abort') {
  131. return abort
  132. } else {
  133. if (Reflect.get(target, prop) && Reflect.get(target, prop).bind) {
  134. return Reflect.get(target, prop).bind(target)
  135. } else {
  136. return Reflect.get(target, prop)
  137. }
  138. }
  139. }
  140. }) // 如果调用 cancel 方法,返回 _watcher.cancel 方法
  141. },
  142. request(method, url, data, header, reqIntercept=true, resIntercept=true) {
  143. let timer, // timer 检测超时定时器
  144. requestTask, // requestTask 网络请求 task 对象
  145. aborted = false, // aborted 请求是否已被取消
  146. overtime = false, // overtime 请求是否超时
  147. abort = () => { // timer 检测超时定时器,requestTask 网络请求 task 对象,aborted 请求是否已被取消,abort 取消请求方法
  148. aborted = true // 将请求状态标记为已取消
  149. requestTask ? requestTask.abort() : '' // 执行取消请求方法
  150. }
  151. return new Proxy(new Promise((resolve, reject) => { // 返回经过 Proxy 后的 Promise 对象使其可以监听到是否调用 abort 方法
  152. this.interceptors.request.intercept({
  153. header: header || {},
  154. body: data || {}
  155. }, method, url, data, reqIntercept).then(async ({
  156. header,
  157. body: data,
  158. cancel
  159. }) => { // 等待请求拦截器里的方法执行完
  160. if (aborted || cancel) { // 如果请求已被取消,停止执行,返回 reject
  161. await this.onerror(method, url, data, '网络请求失败:主动取消')
  162. return reject('网络请求失败:主动取消')
  163. }
  164. requestTask = uni.request({
  165. url: baseURL + url,
  166. data,
  167. method,
  168. header,
  169. success: async res => { // 网络请求成功
  170. // console.log(res,'code....')
  171. // if(res.statusCode == "401"){
  172. // this.onerror(method,url,data)
  173. // }
  174. clearTimeout(timer) // 清除检测超时定时器
  175. this.interceptors.response.intercept(resolve, {
  176. success: true,
  177. ...res,
  178. }, method, url, data, reject,
  179. resIntercept) // 执行响应拦截器
  180. },
  181. fail: async res => { // 网络请求失败
  182. clearTimeout(timer) // 清除检测超时定时器
  183. !overtime && await this.onerror(method, url, data,
  184. aborted ? '网络请求失败:主动取消' :
  185. '网络请求失败:(URL无效|无网络|DNS解析失败)')
  186. aborted ? reject('网络请求失败:主动取消') : reject(
  187. '网络请求失败:(URL无效|无网络|DNS解析失败)')
  188. }
  189. })
  190. timer = setTimeout(async () => { // 请求超时执行方法
  191. overtime = true // 将状态标记为超时,不会被 fail 中的 onerror 重复执行
  192. requestTask.abort() // 执行取消请求方法
  193. await this.onerror(method, url, data, '网络请求失败:超时取消')
  194. reject('网络请求时间超时') // reject 原因
  195. }, timeout || 12345) // 设定检测超时定时器
  196. })
  197. }), {
  198. get: (target, prop) => {
  199. if (prop === 'abort') {
  200. return abort
  201. } else {
  202. if (Reflect.get(target, prop) && Reflect.get(target, prop).bind) {
  203. return Reflect.get(target, prop).bind(target)
  204. } else {
  205. return Reflect.get(target, prop)
  206. }
  207. }
  208. }
  209. }) // 如果调用 abort 方法,返回 abort 方法
  210. },
  211. interceptors: { // 拦截器
  212. request: {
  213. interceptors: [],
  214. use(fun) {
  215. this.interceptors.push(fun)
  216. },
  217. async intercept(config, method, url, data, reqIntercept) {
  218. if (reqIntercept) { // 如果请求允许被拦截
  219. for (let i = 0; i < this.interceptors.length; i++) {
  220. config = await this.interceptors[i](config, method, url, data)
  221. }
  222. }
  223. return config
  224. }
  225. },
  226. response: {
  227. interceptors: [],
  228. use(fun) {
  229. this.interceptors.push(fun)
  230. },
  231. async intercept(STATUS, response, method, url, data, reject, resIntercept) {
  232. try {
  233. if (resIntercept) { // 如果请求允许被拦截
  234. for (let i = 0; i < this.interceptors.length; i++) {
  235. response = await this.interceptors[i](response, method, url, data)
  236. }
  237. }
  238. if (response.success) {
  239. return STATUS(typeof response.data === 'string' ? JSON.parse(response.data) : response
  240. .data)
  241. } else {
  242. delete response.success
  243. return STATUS(response, method, url, data)
  244. }
  245. } catch (e) {
  246. reject(e)
  247. }
  248. }
  249. }
  250. }
  251. }
  252. }