request-queue.js 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import axios from 'axios'
  2. import { objectEqual, cloneDeep } from '@cip/utils/util'
  3. const CancelToken = axios.CancelToken
  4. const equalRequest = (requestSignA, requestSignB) => {
  5. const { url: urlA, query: queryA, data: dateA } = requestSignA
  6. const { url: urlB, query: queryB, data: dateB } = requestSignB
  7. if (urlA !== urlB) return false
  8. if (!objectEqual(queryA, queryB)) return false
  9. if (!objectEqual(dateA, dateB)) return false
  10. return true
  11. }
  12. export class RequestQueue {
  13. constructor (collectionTime = 50) {
  14. this.isSending = false
  15. this.collectionTime = collectionTime
  16. this.requestQueue = [] // 二维数组
  17. }
  18. // delete或者get时第二个参数为config
  19. request ({ method, url, data, config }) { // 需要合并get请求
  20. config.cancelToken = new CancelToken(function (c) {
  21. config._cancel = c
  22. })
  23. if (method !== 'get') { // 非get请求直接放行
  24. return axios({ method, url, data, ...config })
  25. } else {
  26. if (this.isSending === false) {
  27. this.isSending = true
  28. setTimeout(() => {
  29. this.isSending = false
  30. this.send()
  31. }, this.collectionTime)
  32. }
  33. return new Promise((resolve, reject) => {
  34. this.requestQueue.push({ method, url, data, config, resolve, reject })
  35. })
  36. }
  37. }
  38. mergeRequestQueue (requestQueue) {
  39. const result = []
  40. requestQueue.forEach(request => {
  41. const { method, url, data, config, resolve, reject } = request
  42. const { _t, ...query } = config.params // 排除_t对相同判断的影响
  43. const requestSign = { url, query, data } // 使用path、query、header判断是否为同一个请求
  44. const queueSigns = result.map(requests => requests[0])
  45. const queueIndex = queueSigns.findIndex(queueSign => equalRequest(queueSign, requestSign))
  46. if (queueIndex > -1) {
  47. result[queueIndex].push({ resolve, reject })
  48. } else {
  49. result.push([requestSign, { method, url, data, config }, { resolve, reject }])
  50. }
  51. })
  52. return result
  53. }
  54. send () {
  55. const sendRequestQueue = this.mergeRequestQueue(this.requestQueue)
  56. this.requestQueue = []
  57. sendRequestQueue.map(async requestGroup => {
  58. const { method, url, data, config } = requestGroup[1]
  59. axios({ method, url, data, ...config }).then(res => {
  60. this.returnResult(res, 'resolve', requestGroup)
  61. }).catch(err => {
  62. this.returnResult(err, 'reject', requestGroup)
  63. })
  64. })
  65. }
  66. returnResult (res, type, requestGroup) {
  67. if (requestGroup.length > 3) console.log(requestGroup[0].url, '合并', requestGroup.length - 2, '次')
  68. for (let i = 2; i < requestGroup.length; i++) {
  69. if (type === 'reject') {
  70. requestGroup[i][type](res)
  71. } else {
  72. // 深克隆
  73. requestGroup[i][type](cloneDeep(res))
  74. }
  75. }
  76. }
  77. }