uni_request.js 8.1 KB

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