jiangping
2025-03-31 06a46e017886bec692223a626ff50a06b83910cd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import cache from '@/plugins/cache'
import axiosInstance from './index'
const requestMethods = ['get', 'post', 'delete', 'put', 'head', 'options', 'patch', 'request']
const extendsMethods = {}
 
/**
 * 构建基础请求对象Promise代理对象
 *
 * @param method 请求方式
 * @param args 请求参数
 * @returns {{__access(*, *=): *, finally(): *, then(): *, catch(): *, __result_promise: null, __arguments: *}|*}
 */
const buildBasePromiseProxy = (method, args) => {
  return {
    // post,get等请求方法的调用参数
    __arguments: args,
    // 请求结果的promise对象
    __result_promise: null,
    // 代理then方法,直接调用目标promise的then方法
    then () {
      return this.__access('then', arguments)
    },
    // 代理catch方法,直接调用目标promise的catch方法
    catch () {
      return this.__access('catch', arguments)
    },
    // 代理finally方法,直接调用目标promise的finally方法
    finally () {
      return this.__access('finally', arguments)
    },
    __access (methodName, args) {
      if (this.__result_promise != null) {
        return this.__result_promise[methodName].apply(this.__result_promise, args)
      }
      // 发送请求
      if (this.__result_promise == null) {
        this.__result_promise = axiosInstance[method].apply(axiosInstance, this.__arguments)
      }
      // 如果开启了缓存,则在请求成功后写入缓存
      if (this.__with_cache) {
        this.__result_promise.then(data => {
          this.__cache_impl.set(this.__cache_key, data)
          return data
        })
      }
      return this.__result_promise[methodName].apply(this.__result_promise, args)
    }
  }
}
 
/**
 * 构建缓存请求对象Promise代理对象
 *
 * @param cacheKey 缓存key
 * @param method 请求方式
 * @param args 请求参数
 * @param cacheImplName 缓存实现名称
 * @returns {{cache(): *, __with_cache: boolean, __cache_key: *, __cache_impl: *}|Promise<any>|buildCachePromiseProxy}
 */
const buildCachePromiseProxy = (cacheKey, method, args, cacheImplName) => {
  return {
    // 缓存标记
    __with_cache: true,
    // 缓存key
    __cache_key: cacheKey,
    // 缓存实现
    __cache_impl: cache[cacheImplName],
    // 从缓存中获取数据
    cache () {
      // 从缓存中获取数据
      const data = this.__cache_impl.get(cacheKey)
      // 如果从缓存中获取到了数据,则直接构造一个成功的promise
      if (data != null) {
        this.__result_promise = Promise.resolve(data)
      }
      // 如果已经获取到了数据,则由以上成功的promise来接手then和catch的处理
      if (this.__result_promise != null) {
        return this.__result_promise
      }
      return this
    }
  }
}
 
/**
 * 扩展方法:开启缓存
 *
 * @param cacheKey 缓存的key
 * @param isLocal 是否缓存到本地缓存LocalStorage,为false时缓存到SessionStorage
 * @usage:request.cache('test').[post(), get()...]
 * @returns {{isExtendsAxiosInstance: boolean, post: Function, get: Function, ...}}
 */
extendsMethods.cache = function (cacheKey, isLocal = false) {
  if (cacheKey == null) {
    throw Error('Request cache key can not be null.')
  }
  let cacheAxiosInstance = {
    // 标记为axios扩展实例,用于与原生axios作区分
    isExtendsAxiosInstance: true
  }
  if (this.isExtendsAxiosInstance) {
    cacheAxiosInstance = this
  }
  for (const method of requestMethods) {
    if (cacheAxiosInstance[method] == null) {
      cacheAxiosInstance[method] = function () {
        return {
          ...buildBasePromiseProxy(method, arguments),
          ...buildCachePromiseProxy(cacheKey, method, arguments, isLocal ? 'local' : 'session')
        }
      }
      continue
    }
    // 不为null时说明在调用cache前调用了其他扩展方法,此时诸如post,get方法的返回值做合并,防止扩展方法丢失。
    const originMethod = cacheAxiosInstance[method]
    cacheAxiosInstance[method] = function () {
      const request = originMethod()
      Object.assign(request, {
        ...buildBasePromiseProxy(method, arguments),
        ...buildCachePromiseProxy(cacheKey, method, arguments, isLocal ? 'local' : 'session')
      })
      return request
    }
  }
  // 添加扩展方法
  for (const key in extendsMethods) {
    cacheAxiosInstance[key] = extendsMethods[key]
  }
  return cacheAxiosInstance
}
 
export default extendsMethods