@hzab/data-model 2.0.1 → 2.0.3-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # @hzab/data-model@2.0.2
2
+
3
+ fix: getList _data.content total == 0 情况处理
4
+
1
5
  # @hzab/data-model@2.0.1
2
6
 
3
7
  feat: ReqMap 支持异步
package/README.md CHANGED
@@ -127,6 +127,23 @@ function Demo({ orgId }) {
127
127
  }
128
128
  ```
129
129
 
130
+
131
+ #### 重复请求拦截
132
+ ```tsx
133
+ import RequestCache from "@hzab/data-model/RequestCache";
134
+ import { AxiosRequestConfigWithCache, setAxRequest } from "@hzab/data-model";
135
+
136
+ const requestCache = new RequestCache({ options: { cacheTTL: 2000 } });
137
+
138
+ setAxRequest((config: AxiosRequestConfigWithCache) => {
139
+ // 拦截 get 请求
140
+ if (config.method.toLowerCase() === "get") {
141
+ return requestCache.handleAxRequest(config);
142
+ }
143
+ return config;
144
+ });
145
+ ```
146
+
130
147
  ## DataModel
131
148
 
132
149
  | 参数 | 类型 | 必填 | 默认值 | 说明 |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hzab/data-model",
3
- "version": "2.0.1",
3
+ "version": "2.0.3-alpha.0",
4
4
  "description": "data model",
5
5
  "main": "src",
6
6
  "scripts": {
@@ -0,0 +1,202 @@
1
+ import { InternalAxiosRequestConfig } from "axios";
2
+ import { axiosDef } from "./axios";
3
+
4
+ /**
5
+ * 缓存配置
6
+ */
7
+ export interface CacheOpt {
8
+ /** 缓存时间 毫秒 */
9
+ cacheTTL?: number;
10
+ }
11
+
12
+ /**
13
+ * 缓存方法入参配置
14
+ */
15
+ export interface RequestCacheParams {
16
+ options?: CacheOpt;
17
+ }
18
+
19
+ /**
20
+ * 接口入参(用于生成缓存 key)
21
+ */
22
+ export interface Req {
23
+ method?: string;
24
+ baseURL?: string;
25
+ url?: string;
26
+ params?: unknown;
27
+ data?: unknown;
28
+ }
29
+
30
+ /**
31
+ * 缓存对象
32
+ */
33
+ export interface CacheItem {
34
+ key: string;
35
+ /** 过期时间戳 */
36
+ expires?: number;
37
+ /** 缓存的 promise */
38
+ promise?: Promise<unknown>;
39
+ /** 缓存的 axios config 配置 */
40
+ config?: InternalAxiosRequestConfig;
41
+ resolve: (d) => void;
42
+ reject: (err) => void;
43
+ }
44
+
45
+ /**
46
+ * 接口缓存类
47
+ */
48
+ export class RequestCache {
49
+ options: CacheOpt;
50
+ cacheTTL = 3000;
51
+ /** 存储为 CacheItem(类型为 unknown,返回时断言) */
52
+ _cacheMap: Map<string, CacheItem> = new Map();
53
+
54
+ constructor(params: RequestCacheParams) {
55
+ const { options = {} } = params || {};
56
+ this.cacheTTL = options?.cacheTTL ?? 3000;
57
+ this.options = options;
58
+ }
59
+
60
+ /**
61
+ * 处理 axios request 拦截逻辑
62
+ * @param config
63
+ * @returns
64
+ */
65
+ handleAxRequest(config) {
66
+ if (this.hasCache(config)) {
67
+ const cache = this.getCache(config);
68
+ // 存在缓存,
69
+ return Promise.reject({
70
+ code: 200,
71
+ key: this.getCacheKey(config),
72
+ config,
73
+ from: "cache",
74
+ cache,
75
+ });
76
+ }
77
+ this.rmCache(config);
78
+
79
+ const cacheData = {
80
+ code: 200,
81
+ key: this.getCacheKey(config),
82
+ config,
83
+ from: "cache",
84
+ promise: undefined,
85
+ resolve: undefined,
86
+ reject: undefined,
87
+ };
88
+ // 设置 promise 保持请求挂起状态
89
+ cacheData.promise = new Promise((resolve, reject) => {
90
+ cacheData.resolve = resolve;
91
+ cacheData.reject = reject;
92
+ });
93
+
94
+ config.cache = this.addCache(cacheData);
95
+ return config;
96
+ }
97
+
98
+ /**
99
+ * 判断是否存在缓存
100
+ * @param axConf
101
+ * @returns
102
+ */
103
+ hasCache(axConf) {
104
+ const key = this.getCacheKey(axConf);
105
+ const cache = this._cacheMap.get(key);
106
+ if (cache && cache.expires >= Date.now()) {
107
+ return true;
108
+ }
109
+ // 过期清除
110
+ this._cacheMap.delete(key);
111
+ return false;
112
+ }
113
+
114
+ /**
115
+ * 获取缓存
116
+ * @param axios config
117
+ * @param opt 自定义缓存配置
118
+ * @returns Promise<T>
119
+ */
120
+ getCache(axConf, opt?: CacheOpt): CacheItem {
121
+ const key = this.getCacheKey(axConf);
122
+
123
+ return this.getCacheByKey(key, opt);
124
+ }
125
+
126
+ /**
127
+ * 获取缓存
128
+ * @param key string
129
+ * @param opt 自定义缓存配置
130
+ * @returns Promise<T>
131
+ */
132
+ getCacheByKey(key, opt?: CacheOpt) {
133
+ // TODO: 过期处理? 结果和请求分开。只有请求才进行过期判断?
134
+ // 存在未过期的缓存
135
+ const cached = this._cacheMap.get(key);
136
+ if (cached && cached.expires > Date.now()) {
137
+ return cached;
138
+ }
139
+
140
+ // 过期删除
141
+ if (cached) {
142
+ this._cacheMap.delete(key);
143
+ }
144
+ }
145
+
146
+ /**
147
+ * 添加缓存
148
+ * @param promise 要缓存的 Promise
149
+ * @param req 请求描述对象
150
+ * @param config 缓存配置
151
+ */
152
+ addCache(data: CacheItem, opt: CacheOpt = this.options): CacheItem {
153
+ const { config } = data || {};
154
+ const key = this.getCacheKey(config);
155
+ if (this._cacheMap.has(key)) {
156
+ return this._cacheMap.get(key);
157
+ }
158
+ const ttl = opt?.cacheTTL ?? this.cacheTTL;
159
+ const cache = {
160
+ ...data,
161
+ key,
162
+ expires: Date.now() + ttl,
163
+ config: config,
164
+ promise: data.promise,
165
+ };
166
+ this._cacheMap.set(key, cache);
167
+ return cache;
168
+ }
169
+
170
+ rmCache(config: Req) {
171
+ this._cacheMap.delete(this.getCacheKey(config));
172
+ }
173
+
174
+ /**
175
+ * 获取缓存的 key
176
+ * @param config 请求入参
177
+ * @returns 缓存键字符串
178
+ */
179
+ getCacheKey(config: Req): string {
180
+ const { baseURL, method, url, params, data } = config;
181
+ // 注意:params 和 data 需要序列化,并保证对象属性顺序稳定性
182
+ return `${method}:${baseURL}/${url}:${this.stableStringify(params)}:${this.stableStringify(data)}`;
183
+ }
184
+
185
+ /**
186
+ * 序列化对象,保证属性顺序一致
187
+ * @param obj 任意值
188
+ * @returns JSON 字符串
189
+ */
190
+ private stableStringify(obj: unknown): string {
191
+ if (!obj || typeof obj !== "object") return JSON.stringify(obj);
192
+ const sorted = Object.keys(obj)
193
+ .sort()
194
+ .reduce((acc, key) => {
195
+ acc[key] = (obj as Record<string, unknown>)[key];
196
+ return acc;
197
+ }, {} as Record<string, unknown>);
198
+ return JSON.stringify(sorted);
199
+ }
200
+ }
201
+
202
+ export default RequestCache;