uni_request.js 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. export default function ({ baseURL, timeout, header }) {
  2. return {
  3. get(url, data) { return this.request('GET', url, data) },
  4. post(url, data) { return this.request('POST', url, data) },
  5. put(url, data) { return this.request('PUT', url, data) },
  6. delete(url, data) { return this.request('DELETE', url, data) },
  7. connect(url, data) { return this.request('CONNECT', url, data) },
  8. head(url, data) { return this.request('HEAD', url, data) },
  9. options(url, data) { return this.request('OPTIONS', url, data) },
  10. reace(url, data) { return this.request('TRACE', url, data) },
  11. uploadFile(url, data) { return this.file('uploadFile', url, data || {}) },
  12. downloadFile(url, data) { return this.file('downloadFile', url, data || {}) },
  13. onerror: [], // 请求错误钩子函数集合
  14. file(method, url, data) {
  15. let timer, requestTask, aborted = false, abort = () => { // timer 检测超时定时器,requestTask 网络请求 task 对象,aborted 请求是否已被取消,abort 取消请求方法
  16. aborted = true // 将请求状态标记为已取消
  17. requestTask ? requestTask.abort() : '' // 执行取消请求方法
  18. }, progressUpdateHandle, onProgressUpdate = e => progressUpdateHandle = e // progressUpdateHandle 监听上传进度变化回调,onProgressUpdate 监听上传进度变化方法
  19. return new Proxy(new Promise((resolve, reject) => { // 返回经过 Proxy 后的 Promise 对象使其可以监听到是否调用 abort 和 onProgressUpdate 方法
  20. this.interceptors.request.intercept({ header: data.header || {}, body: data.formData || {} }, method, url, data).then(async ({ header, body }) => { // 等待请求拦截器里的方法执行完
  21. if (aborted) { // 如果请求已被取消,停止执行,返回 reject
  22. await this.onerror(method, url, data, '网络请求失败:主动取消')
  23. return reject('网络请求失败:主动取消')
  24. }
  25. requestTask = uni[method]({
  26. url: url[0] === '/' ? baseURL + url : url,
  27. name: data.name,
  28. header,
  29. filePath: data.filePath,
  30. formData: body,
  31. success: async res => {
  32. clearTimeout(timer)
  33. res.statusCode !== 200 ? await this.onerror(method, url, data, `网络请求异常:服务器响应异常:状态码:${res.statusCode}`) : '',
  34. this.interceptors.response.intercept(res.statusCode === 200 ? resolve : reject, { success: res.statusCode === 200, ...res }, method, url, data) // 执行响应拦截器
  35. },
  36. fail: async res => {
  37. clearTimeout(timer)
  38. await this.onerror(method, url, data, aborted ? '网络请求失败:主动取消' : '网络请求失败:(URL无效|无网络|DNS解析失败)')
  39. aborted ? reject('网络请求失败:主动取消') : reject('网络请求失败:(URL无效|无网络|DNS解析失败)')
  40. }
  41. })
  42. requestTask.onProgressUpdate(progressUpdateHandle) // 监听下载进度变化
  43. timer = setTimeout(async () => { // 请求超时执行方法
  44. requestTask.abort() // 执行取消请求方法
  45. await this.onerror(method, url, data, '网络请求失败:超时取消')
  46. reject('网络请求时间超时') // reject 原因
  47. }, timeout || 12345) // 设定检测超时定时器
  48. })
  49. }), { get: (target, prop) => prop === 'abort' ? abort : prop === 'onProgressUpdate' ? onProgressUpdate : Reflect.get(target, prop).bind(target) }) // 如果调用 cancel 方法,返回 _watcher.cancel 方法
  50. },
  51. request(method, url, data) {
  52. let timer, requestTask, aborted = false, abort = () => { // timer 检测超时定时器,requestTask 网络请求 task 对象,aborted 请求是否已被取消,abort 取消请求方法
  53. aborted = true // 将请求状态标记为已取消
  54. requestTask ? requestTask.abort() : '' // 执行取消请求方法
  55. }
  56. return new Proxy(new Promise((resolve, reject) => { // 返回经过 Proxy 后的 Promise 对象使其可以监听到是否调用 abort 方法
  57. this.interceptors.request.intercept({ header: header || {}, body: data || {} }, method, url, data).then(async ({ header, body: data }) => { // 等待请求拦截器里的方法执行完
  58. if (aborted) { // 如果请求已被取消,停止执行,返回 reject
  59. await this.onerror(method, url, data, '网络请求失败:主动取消')
  60. return reject('网络请求失败:主动取消')
  61. }
  62. requestTask = uni.request({
  63. url: url[0] === '/' ? baseURL + url : url,
  64. data, method, header,
  65. success: async res => { // 网络请求成功
  66. clearTimeout(timer) // 清除检测超时定时器
  67. res.statusCode !== 200 ? await this.onerror(method, url, data, `网络请求异常:服务器响应异常:状态码:${res.statusCode}`) : ''
  68. this.interceptors.response.intercept(res.statusCode === 200 ? resolve : reject, { success: res.statusCode === 200, ...res }, method, url, data) // 执行响应拦截器
  69. },
  70. fail: async res => { // 网络请求失败
  71. uni.showModal({
  72. content: JSON.stringify(res)
  73. })
  74. clearTimeout(timer) // 清除检测超时定时器
  75. await this.onerror(method, url, data, aborted ? '网络请求失败:主动取消' : '网络请求失败:(URL无效|无网络|DNS解析失败)')
  76. aborted ? reject('网络请求失败:主动取消') : reject('网络请求失败:(URL无效|无网络|DNS解析失败)')
  77. }
  78. })
  79. timer = setTimeout(async () => { // 请求超时执行方法
  80. requestTask.abort() // 执行取消请求方法
  81. await this.onerror(method, url, data, '网络请求失败:超时取消')
  82. reject('网络请求时间超时') // reject 原因
  83. }, timeout || 12345) // 设定检测超时定时器
  84. })
  85. }), { get: (target, prop) => prop === 'abort' ? abort : Reflect.get(target, prop).bind(target) }) // 如果调用 abort 方法,返回 abort 方法
  86. },
  87. interceptors: { // 拦截器
  88. request: {
  89. interceptors: [],
  90. use(fun) { this.interceptors.push(fun) },
  91. async intercept(config, method, url, data) {
  92. for (let i = 0; i < this.interceptors.length; i ++) {
  93. config = await this.interceptors[i](config, method, url, data)
  94. }
  95. return config
  96. }
  97. },
  98. response: {
  99. interceptors: [],
  100. use(fun) { this.interceptors.push(fun) },
  101. async intercept(STATUS, response, method, url, data) {
  102. for (let i = 0; i < this.interceptors.length; i ++) {
  103. response = await this.interceptors[i](response, method, url, data)
  104. }
  105. if (response.success) {
  106. try {
  107. return STATUS(typeof response.data === 'string' ? JSON.parse(response.data) : response.data)
  108. } catch(e) {
  109. return STATUS(response.data)
  110. }
  111. } else {
  112. delete response.success
  113. return STATUS(response, method, url, data)
  114. }
  115. }
  116. }
  117. }
  118. }
  119. }