rxtutils 1.1.4-beta.9 → 1.1.6
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/README.md +117 -49
- package/cjs/_utils/defaultEquals.cjs +4 -19
- package/cjs/cache/index.cjs +130 -163
- package/cjs/cache/indexDB.cjs +86 -99
- package/cjs/downloadBlob.cjs +14 -0
- package/cjs/hooks/index.cjs +3 -6
- package/cjs/hooks/useCombineControlValue.cjs +33 -41
- package/cjs/index.cjs +16 -17
- package/cjs/request/defaultHandlers.cjs +5 -27
- package/cjs/request/error.cjs +18 -30
- package/cjs/request/index.cjs +194 -174
- package/cjs/store/createGetter/index.cjs +26 -40
- package/cjs/store/createStateStore/index.cjs +47 -90
- package/cjs/store/index.cjs +4 -7
- package/cjs/validator/decorators.cjs +71 -228
- package/cjs/validator/index.cjs +4 -7
- package/cjs/validator/validator.cjs +101 -177
- package/es/_utils/defaultEquals.mjs +4 -17
- package/es/cache/index.d.ts +9 -13
- package/es/cache/index.mjs +132 -160
- package/es/cache/indexDB.d.ts +1 -3
- package/es/cache/indexDB.mjs +87 -98
- package/es/downloadBlob.d.ts +8 -0
- package/es/downloadBlob.mjs +14 -0
- package/es/hooks/index.d.ts +1 -1
- package/es/hooks/index.mjs +4 -1
- package/es/hooks/useCombineControlValue.d.ts +5 -8
- package/es/hooks/useCombineControlValue.mjs +34 -40
- package/es/index.d.ts +28 -8
- package/es/index.mjs +29 -7
- package/es/request/defaultHandlers.d.ts +24 -0
- package/es/request/defaultHandlers.mjs +8 -26
- package/es/request/error.d.ts +3 -6
- package/es/request/error.mjs +18 -28
- package/es/request/index.d.ts +32 -20
- package/es/request/index.mjs +194 -172
- package/es/store/createGetter/index.d.ts +6 -10
- package/es/store/createGetter/index.mjs +28 -39
- package/es/store/createStateStore/index.d.ts +9 -9
- package/es/store/createStateStore/index.mjs +49 -87
- package/es/store/index.d.ts +4 -2
- package/es/store/index.mjs +7 -2
- package/es/validator/decorators.d.ts +12 -21
- package/es/validator/decorators.mjs +81 -226
- package/es/validator/index.d.ts +2 -2
- package/es/validator/index.mjs +16 -2
- package/es/validator/validator.d.ts +5 -6
- package/es/validator/validator.mjs +102 -176
- package/package.json +85 -15
- package/cjs/_utils/deepAssign.cjs +0 -25
- package/cjs/cache/index.d.ts +0 -141
- package/cjs/cache/indexDB.d.ts +0 -52
- package/cjs/hooks/index.d.ts +0 -1
- package/cjs/hooks/useCombineControlValue.d.ts +0 -21
- package/cjs/index.d.ts +0 -8
- package/cjs/request/error.d.ts +0 -31
- package/cjs/request/index.d.ts +0 -147
- package/cjs/store/createGetter/index.d.ts +0 -30
- package/cjs/store/createStateStore/index.d.ts +0 -42
- package/cjs/store/index.d.ts +0 -2
- package/cjs/validator/decorators.d.ts +0 -159
- package/cjs/validator/index.d.ts +0 -2
- package/cjs/validator/validator.d.ts +0 -84
- package/es/_utils/deepAssign.mjs +0 -23
package/README.md
CHANGED
|
@@ -12,6 +12,12 @@ yarn add rxtutils
|
|
|
12
12
|
pnpm add rxtutils
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
+
也支持按需导入子模块(如 `rxtutils/cache`, `rxtutils/hooks` 等)。
|
|
16
|
+
|
|
17
|
+
### ⚠️ 环境要求
|
|
18
|
+
|
|
19
|
+
本库的构建目标为 **ES2020**。如果在低版本环境中使用,请确保配置了相应的 Polyfill 或构建转译。
|
|
20
|
+
|
|
15
21
|
## 🚀 功能特性
|
|
16
22
|
|
|
17
23
|
- **缓存管理** - 支持内存、localStorage、sessionStorage 和 IndexedDB 多种存储方式
|
|
@@ -67,7 +73,7 @@ const customCache = new Cache<{ id: number; name: string }, any>(
|
|
|
67
73
|
'customCache',
|
|
68
74
|
300,
|
|
69
75
|
'customDB',
|
|
70
|
-
(prev, next) => prev.id === next.id // 只比较 id 字段
|
|
76
|
+
(prev, next) => prev.id === next.id, // 只比较 id 字段
|
|
71
77
|
);
|
|
72
78
|
```
|
|
73
79
|
|
|
@@ -84,13 +90,13 @@ import { createBaseRequest } from 'rxtutils';
|
|
|
84
90
|
const request = createBaseRequest({
|
|
85
91
|
baseURL: 'https://api.example.com',
|
|
86
92
|
throwError: true,
|
|
87
|
-
defaultMessageShower: (message) => console.log(message)
|
|
93
|
+
defaultMessageShower: (message) => console.log(message),
|
|
88
94
|
});
|
|
89
95
|
|
|
90
96
|
// 创建具体请求
|
|
91
97
|
const getUserInfo = request<{ id: number }, { name: string; email: string }>({
|
|
92
98
|
method: 'GET',
|
|
93
|
-
url: '/user/:id'
|
|
99
|
+
url: '/user/:id',
|
|
94
100
|
});
|
|
95
101
|
|
|
96
102
|
// 发送请求
|
|
@@ -107,13 +113,13 @@ const request = createBaseRequest({
|
|
|
107
113
|
'401': '未授权,请重新登录',
|
|
108
114
|
'500': (code, data, res) => ({
|
|
109
115
|
replaceResData: { error: '服务器内部错误' },
|
|
110
|
-
throwError: false
|
|
111
|
-
})
|
|
116
|
+
throwError: false,
|
|
117
|
+
}),
|
|
112
118
|
},
|
|
113
119
|
httpErrorCodeMap: {
|
|
114
120
|
404: '资源不存在',
|
|
115
|
-
500: '服务器错误'
|
|
116
|
-
}
|
|
121
|
+
500: '服务器错误',
|
|
122
|
+
},
|
|
117
123
|
});
|
|
118
124
|
```
|
|
119
125
|
|
|
@@ -126,7 +132,7 @@ const request = createBaseRequest({
|
|
|
126
132
|
cacheData: true,
|
|
127
133
|
cacheDataInStorage: 'localStorage',
|
|
128
134
|
cacheDataKey: 'api-cache',
|
|
129
|
-
cacheTime: 300
|
|
135
|
+
cacheTime: 300,
|
|
130
136
|
});
|
|
131
137
|
|
|
132
138
|
// 第一次请求会从服务器获取数据
|
|
@@ -158,7 +164,7 @@ const userStore = createStateStore({
|
|
|
158
164
|
// 在组件中使用
|
|
159
165
|
function UserComponent() {
|
|
160
166
|
const [user, setUser] = userStore.use();
|
|
161
|
-
|
|
167
|
+
|
|
162
168
|
const handleLogin = () => {
|
|
163
169
|
setUser({
|
|
164
170
|
name: 'John Doe',
|
|
@@ -166,7 +172,7 @@ function UserComponent() {
|
|
|
166
172
|
isLoggedIn: true
|
|
167
173
|
});
|
|
168
174
|
};
|
|
169
|
-
|
|
175
|
+
|
|
170
176
|
return (
|
|
171
177
|
<div>
|
|
172
178
|
<p>用户名: {user.name}</p>
|
|
@@ -274,12 +280,10 @@ console.log(allErrors); // 返回所有验证错误
|
|
|
274
280
|
import { BaseValidator } from 'rxtutils';
|
|
275
281
|
|
|
276
282
|
// 创建自定义验证装饰器
|
|
277
|
-
const VCustom = BaseValidator.decoratorCreator(
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
}
|
|
282
|
-
);
|
|
283
|
+
const VCustom = BaseValidator.decoratorCreator((val) => {
|
|
284
|
+
// 自定义验证逻辑
|
|
285
|
+
return typeof val === 'string' && val.startsWith('custom-');
|
|
286
|
+
});
|
|
283
287
|
|
|
284
288
|
// 使用自定义验证装饰器
|
|
285
289
|
class Product extends BaseValidator {
|
|
@@ -329,7 +333,7 @@ form.password = '123456';
|
|
|
329
333
|
|
|
330
334
|
// 验证单个字段的所有规则
|
|
331
335
|
const usernameErrors = form.validate('username', true);
|
|
332
|
-
console.log(usernameErrors);
|
|
336
|
+
console.log(usernameErrors);
|
|
333
337
|
// [{ status: false, message: '用户名长度不能少于3位' }]
|
|
334
338
|
|
|
335
339
|
// 验证所有字段,每个字段遇到第一个错误就停止
|
|
@@ -379,7 +383,7 @@ const useUserGetters = createStoreGetterMemo(userStore, getters, getterNameMaps)
|
|
|
379
383
|
|
|
380
384
|
function UserProfile() {
|
|
381
385
|
const { fullName, isAdult, displayName } = useUserGetters();
|
|
382
|
-
|
|
386
|
+
|
|
383
387
|
return (
|
|
384
388
|
<div>
|
|
385
389
|
<h1>{fullName}</h1>
|
|
@@ -394,26 +398,26 @@ function UserProfile() {
|
|
|
394
398
|
|
|
395
399
|
### Cache 配置
|
|
396
400
|
|
|
397
|
-
| 参数
|
|
398
|
-
|
|
399
|
-
| `storageType`
|
|
400
|
-
| `cacheKey`
|
|
401
|
-
| `cacheTime`
|
|
402
|
-
| `indexDBName`
|
|
403
|
-
| `cacheKeyEquals` | `function`
|
|
401
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
402
|
+
| ---------------- | --------------------------------------------------- | ------------------------ | -------------------- |
|
|
403
|
+
| `storageType` | `'sessionStorage' \| 'localStorage' \| 'indexedDB'` | `undefined` | 存储类型 |
|
|
404
|
+
| `cacheKey` | `string` | `undefined` | 缓存键名 |
|
|
405
|
+
| `cacheTime` | `number` | `60` | 缓存时间(秒) |
|
|
406
|
+
| `indexDBName` | `string` | `'__apiCacheDatabase__'` | IndexedDB 数据库名称 |
|
|
407
|
+
| `cacheKeyEquals` | `function` | `defaultEquals` | 缓存键比较函数 |
|
|
404
408
|
|
|
405
409
|
### Request 配置
|
|
406
410
|
|
|
407
|
-
| 参数
|
|
408
|
-
|
|
409
|
-
| `baseURL`
|
|
410
|
-
| `throwError`
|
|
411
|
-
| `enableCache`
|
|
412
|
-
| `cacheData`
|
|
413
|
-
| `cacheTime`
|
|
414
|
-
| `cacheDataInStorage` | `StorageType` | `undefined`
|
|
415
|
-
| `errorCodePath`
|
|
416
|
-
| `successCodes`
|
|
411
|
+
| 参数 | 类型 | 默认值 | 说明 |
|
|
412
|
+
| -------------------- | ------------- | -------------- | -------------- |
|
|
413
|
+
| `baseURL` | `string` | `''` | 请求基础URL |
|
|
414
|
+
| `throwError` | `boolean` | `true` | 是否抛出错误 |
|
|
415
|
+
| `enableCache` | `boolean` | `false` | 是否启用缓存 |
|
|
416
|
+
| `cacheData` | `boolean` | `false` | 是否缓存数据 |
|
|
417
|
+
| `cacheTime` | `number` | `60` | 缓存时间(秒) |
|
|
418
|
+
| `cacheDataInStorage` | `StorageType` | `undefined` | 缓存存储类型 |
|
|
419
|
+
| `errorCodePath` | `string` | `'code'` | 错误码路径 |
|
|
420
|
+
| `successCodes` | `string[]` | `['0', '200']` | 成功状态码 |
|
|
417
421
|
|
|
418
422
|
## 📝 类型定义
|
|
419
423
|
|
|
@@ -487,12 +491,12 @@ const apiRequest = createBaseRequest({
|
|
|
487
491
|
enableCache: true,
|
|
488
492
|
cacheData: true,
|
|
489
493
|
cacheDataInStorage: 'localStorage',
|
|
490
|
-
cacheTime: 300
|
|
494
|
+
cacheTime: 300,
|
|
491
495
|
});
|
|
492
496
|
|
|
493
497
|
const getProductList = apiRequest<{ page: number }, { products: Product[] }>({
|
|
494
498
|
method: 'GET',
|
|
495
|
-
url: '/products'
|
|
499
|
+
url: '/products',
|
|
496
500
|
});
|
|
497
501
|
```
|
|
498
502
|
|
|
@@ -503,19 +507,23 @@ const getProductList = apiRequest<{ page: number }, { products: Product[] }>({
|
|
|
503
507
|
const userStore = createStateStore({
|
|
504
508
|
user: null,
|
|
505
509
|
permissions: [],
|
|
506
|
-
theme: 'light'
|
|
510
|
+
theme: 'light',
|
|
507
511
|
});
|
|
508
512
|
|
|
509
513
|
// 创建用户相关的计算属性
|
|
510
|
-
const userGetters = createStoreGetter(
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
514
|
+
const userGetters = createStoreGetter(
|
|
515
|
+
userStore,
|
|
516
|
+
{
|
|
517
|
+
isLoggedIn: (state) => !!state.user,
|
|
518
|
+
canEdit: (state) => state.permissions.includes('edit'),
|
|
519
|
+
isDarkTheme: (state) => state.theme === 'dark',
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
isLoggedIn: 'isLoggedIn',
|
|
523
|
+
canEdit: 'canEdit',
|
|
524
|
+
isDarkTheme: 'isDarkTheme',
|
|
525
|
+
},
|
|
526
|
+
);
|
|
519
527
|
```
|
|
520
528
|
|
|
521
529
|
### 3. 表单数据缓存
|
|
@@ -531,9 +539,69 @@ formCache.setCache('user-form', formData);
|
|
|
531
539
|
const savedData = formCache.getCache('user-form');
|
|
532
540
|
```
|
|
533
541
|
|
|
542
|
+
## 🛠 开发
|
|
543
|
+
|
|
544
|
+
本项目包含一个 playground 用于调试和预览。
|
|
545
|
+
|
|
546
|
+
```bash
|
|
547
|
+
# 安装依赖
|
|
548
|
+
pnpm install --frozen-lockfile
|
|
549
|
+
|
|
550
|
+
# 启动开发服务器
|
|
551
|
+
pnpm dev
|
|
552
|
+
|
|
553
|
+
# 运行测试
|
|
554
|
+
pnpm test
|
|
555
|
+
|
|
556
|
+
# 代码检查
|
|
557
|
+
pnpm lint
|
|
558
|
+
|
|
559
|
+
# 代码格式化
|
|
560
|
+
pnpm format
|
|
561
|
+
|
|
562
|
+
# 类型检查
|
|
563
|
+
pnpm typecheck
|
|
564
|
+
|
|
565
|
+
# 构建
|
|
566
|
+
pnpm build
|
|
567
|
+
```
|
|
568
|
+
|
|
534
569
|
## 🤝 贡献
|
|
535
570
|
|
|
536
|
-
欢迎提交 Issue 和 Pull Request
|
|
571
|
+
欢迎提交 Issue 和 Pull Request 来帮助改进这个项目。提交前建议先执行:
|
|
572
|
+
|
|
573
|
+
```bash
|
|
574
|
+
pnpm format:check
|
|
575
|
+
pnpm lint
|
|
576
|
+
pnpm typecheck
|
|
577
|
+
pnpm test
|
|
578
|
+
pnpm build
|
|
579
|
+
```
|
|
580
|
+
|
|
581
|
+
## 🔧 Git Alias(可选)
|
|
582
|
+
|
|
583
|
+
如果你习惯使用 Git alias,建议配置到个人环境(`~/.gitconfig`),而不是放在仓库中。
|
|
584
|
+
|
|
585
|
+
方式一:逐条命令配置
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
git config --global alias.cm commit
|
|
589
|
+
git config --global alias.cc checkout
|
|
590
|
+
git config --global alias.bc branch
|
|
591
|
+
git config --global alias.df diff
|
|
592
|
+
git config --global alias.lg log
|
|
593
|
+
```
|
|
594
|
+
|
|
595
|
+
方式二:直接追加配置片段到 `~/.gitconfig`
|
|
596
|
+
|
|
597
|
+
```ini
|
|
598
|
+
[alias]
|
|
599
|
+
cm = commit
|
|
600
|
+
cc = checkout
|
|
601
|
+
bc = branch
|
|
602
|
+
df = diff
|
|
603
|
+
lg = log
|
|
604
|
+
```
|
|
537
605
|
|
|
538
606
|
## 📄 许可证
|
|
539
607
|
|
|
@@ -544,4 +612,4 @@ MIT License
|
|
|
544
612
|
- [TypeScript](https://www.typescriptlang.org/)
|
|
545
613
|
- [React](https://reactjs.org/)
|
|
546
614
|
- [Axios](https://axios-http.com/)
|
|
547
|
-
- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
|
|
615
|
+
- [IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API)
|
|
@@ -1,21 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 默认的相等性比较函数
|
|
5
|
-
* 通过将两个值序列化为 JSON 字符串来比较它们是否相等
|
|
6
|
-
*
|
|
7
|
-
* @template Param 比较值的类型,默认为 any
|
|
8
|
-
* @param prev 前一个值
|
|
9
|
-
* @param next 后一个值
|
|
10
|
-
* @returns {boolean} 如果两个值相等则返回 true,否则返回 false
|
|
11
|
-
*
|
|
12
|
-
* @remarks
|
|
13
|
-
* - 这个函数通过 JSON.stringify 进行比较,适用于大多数简单的数据结构
|
|
14
|
-
* - 不适用于包含函数、undefined、Symbol 等无法序列化的值
|
|
15
|
-
* - 对于循环引用的对象会抛出错误
|
|
16
|
-
*/
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
17
3
|
function defaultEquals(prev, next) {
|
|
18
|
-
|
|
4
|
+
return JSON.stringify(prev) === JSON.stringify(next);
|
|
19
5
|
}
|
|
20
|
-
|
|
21
|
-
module.exports = defaultEquals;
|
|
6
|
+
exports.default = defaultEquals;
|
package/cjs/cache/index.cjs
CHANGED
|
@@ -1,170 +1,137 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/** 存储类型映射表 */
|
|
11
|
-
var StorageMap = {
|
|
12
|
-
localStorage: localStorage,
|
|
13
|
-
sessionStorage: sessionStorage,
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
|
+
const dateFns = require("date-fns");
|
|
4
|
+
const indexDB = require("./indexDB.cjs");
|
|
5
|
+
const defaultEquals = require("../_utils/defaultEquals.cjs");
|
|
6
|
+
const StorageMap = {
|
|
7
|
+
localStorage,
|
|
8
|
+
sessionStorage
|
|
14
9
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
/** 内存中的缓存数组 */
|
|
33
|
-
this.cache = [];
|
|
34
|
-
this.cacheOptions = {
|
|
35
|
-
storageType: cacheType,
|
|
36
|
-
cacheKey: cacheKey,
|
|
37
|
-
cacheTime: cacheTime,
|
|
38
|
-
indexDBName: indexDBName,
|
|
39
|
-
cacheKeyEquals: cacheKeyEquals,
|
|
40
|
-
};
|
|
41
|
-
if (cacheType === "indexedDB") {
|
|
42
|
-
this.storage = new indexDB.IndexedDBStorage(indexDBName, "cacheStore");
|
|
43
|
-
}
|
|
44
|
-
else if (typeof cacheType === "string") {
|
|
45
|
-
this.storage = StorageMap[cacheType];
|
|
46
|
-
}
|
|
47
|
-
this._init();
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* 初始化缓存
|
|
51
|
-
* 从存储中加载已保存的缓存数据,并进行解析和过期处理
|
|
52
|
-
* @private
|
|
53
|
-
*/
|
|
54
|
-
Cache.prototype._init = function () {
|
|
55
|
-
return tslib.__awaiter(this, void 0, void 0, function () {
|
|
56
|
-
var _a, cacheType, cacheKey, _b, _c, _d;
|
|
57
|
-
return tslib.__generator(this, function (_e) {
|
|
58
|
-
switch (_e.label) {
|
|
59
|
-
case 0:
|
|
60
|
-
_a = this.cacheOptions, cacheType = _a.storageType, cacheKey = _a.cacheKey;
|
|
61
|
-
if (!(this.storage instanceof indexDB.IndexedDBStorage)) return [3 /*break*/, 2];
|
|
62
|
-
_b = this;
|
|
63
|
-
_d = (_c = JSON).parse;
|
|
64
|
-
return [4 /*yield*/, this.storage.getItem(cacheKey)];
|
|
65
|
-
case 1:
|
|
66
|
-
_b.cache = _d.apply(_c, [(_e.sent()) || "[]"]);
|
|
67
|
-
return [3 /*break*/, 3];
|
|
68
|
-
case 2:
|
|
69
|
-
if (this.storage instanceof Storage) {
|
|
70
|
-
this.storage = StorageMap[cacheType];
|
|
71
|
-
if (this.storage) {
|
|
72
|
-
if (typeof cacheKey === "string") {
|
|
73
|
-
try {
|
|
74
|
-
this.cache = JSON.parse(this.storage.getItem(cacheKey) || "[]");
|
|
75
|
-
}
|
|
76
|
-
catch (e) {
|
|
77
|
-
this.cache = [];
|
|
78
|
-
console.error("\u7F13\u5B58\u6570\u636E\u89E3\u6790\u5931\u8D25\uFF0Ckey:".concat(cacheKey));
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
_e.label = 3;
|
|
84
|
-
case 3:
|
|
85
|
-
this._filterExpired();
|
|
86
|
-
this._saveToStorage();
|
|
87
|
-
return [2 /*return*/];
|
|
88
|
-
}
|
|
89
|
-
});
|
|
90
|
-
});
|
|
91
|
-
};
|
|
92
|
-
/**
|
|
93
|
-
* 过滤掉已过期的缓存项
|
|
94
|
-
* 通过比较当前时间和过期时间,移除过期的缓存项
|
|
95
|
-
* @private
|
|
96
|
-
*/
|
|
97
|
-
Cache.prototype._filterExpired = function () {
|
|
98
|
-
var newCache = this.cache.filter(function (item) {
|
|
99
|
-
return moment(item.expireTime).isAfter(moment());
|
|
100
|
-
});
|
|
101
|
-
this.cache = newCache;
|
|
10
|
+
class Cache {
|
|
11
|
+
/**
|
|
12
|
+
* 构造函数
|
|
13
|
+
* @param cacheType 存储类型
|
|
14
|
+
* @param cacheKey 缓存键名
|
|
15
|
+
* @param cacheTime 缓存时间(秒)
|
|
16
|
+
* @param indexDBName IndexedDB 数据库名称,默认值为 '__apiCacheDatabase__'
|
|
17
|
+
* @param cacheKeyEquals 缓存键比较函数,默认使用 defaultEquals
|
|
18
|
+
*/
|
|
19
|
+
constructor(cacheType, cacheKey, cacheTime, indexDBName = "__apiCacheDatabase__", cacheKeyEquals = defaultEquals.default) {
|
|
20
|
+
this.cache = [];
|
|
21
|
+
this.cacheOptions = {
|
|
22
|
+
storageType: cacheType,
|
|
23
|
+
cacheKey,
|
|
24
|
+
cacheTime,
|
|
25
|
+
indexDBName,
|
|
26
|
+
cacheKeyEquals
|
|
102
27
|
};
|
|
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
|
-
this.cache.push({
|
|
130
|
-
params: params,
|
|
131
|
-
data: data,
|
|
132
|
-
expireTime: moment().add(cacheTime, "seconds").toJSON(),
|
|
133
|
-
});
|
|
134
|
-
this._saveToStorage();
|
|
135
|
-
};
|
|
136
|
-
/**
|
|
137
|
-
* 获取缓存数据
|
|
138
|
-
* @param params 查询参数
|
|
139
|
-
* @returns 如果找到有效的缓存数据则返回数据,否则返回 null
|
|
140
|
-
*/
|
|
141
|
-
Cache.prototype.getCache = function (params) {
|
|
142
|
-
var _this = this;
|
|
143
|
-
var itemIndex = this.cache.findIndex(function (item) {
|
|
144
|
-
return _this.cacheOptions.cacheKeyEquals(item.params, params);
|
|
145
|
-
});
|
|
146
|
-
var item = this.cache[itemIndex];
|
|
147
|
-
if (item) {
|
|
148
|
-
if (moment(item.expireTime).isAfter(moment())) {
|
|
149
|
-
return item.data;
|
|
150
|
-
}
|
|
151
|
-
else {
|
|
152
|
-
this.cache.splice(itemIndex, 1);
|
|
153
|
-
this._saveToStorage();
|
|
154
|
-
}
|
|
28
|
+
if (cacheType === "indexedDB") {
|
|
29
|
+
this.storage = new indexDB.IndexedDBStorage(indexDBName, "cacheStore");
|
|
30
|
+
} else if (typeof cacheType === "string") {
|
|
31
|
+
this.storage = StorageMap[cacheType];
|
|
32
|
+
}
|
|
33
|
+
this._init();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 初始化缓存
|
|
37
|
+
* 从存储中加载已保存的缓存数据,并进行解析和过期处理
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
async _init() {
|
|
41
|
+
const { storageType: cacheType, cacheKey } = this.cacheOptions;
|
|
42
|
+
if (this.storage instanceof indexDB.IndexedDBStorage) {
|
|
43
|
+
this.cache = JSON.parse(await this.storage.getItem(cacheKey) || "[]");
|
|
44
|
+
} else if (this.storage instanceof Storage) {
|
|
45
|
+
this.storage = StorageMap[cacheType];
|
|
46
|
+
if (this.storage) {
|
|
47
|
+
if (typeof cacheKey === "string") {
|
|
48
|
+
try {
|
|
49
|
+
this.cache = JSON.parse(this.storage.getItem(cacheKey) || "[]");
|
|
50
|
+
} catch (e) {
|
|
51
|
+
this.cache = [];
|
|
52
|
+
console.error(`缓存数据解析失败,key:${cacheKey}`);
|
|
53
|
+
}
|
|
155
54
|
}
|
|
156
|
-
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
this._filterExpired();
|
|
58
|
+
this._saveToStorage();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* 过滤掉已过期的缓存项
|
|
62
|
+
* 通过比较当前时间和过期时间,移除过期的缓存项
|
|
63
|
+
* @private
|
|
64
|
+
*/
|
|
65
|
+
_filterExpired() {
|
|
66
|
+
const newCache = this.cache.filter((item) => {
|
|
67
|
+
return dateFns.isAfter(dateFns.parseISO(item.expireTime), /* @__PURE__ */ new Date());
|
|
68
|
+
});
|
|
69
|
+
this.cache = newCache;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* 将当前缓存数据保存到存储中
|
|
73
|
+
* 如果设置了缓存键名且存储实例存在,则将缓存数据序列化后保存
|
|
74
|
+
* @private
|
|
75
|
+
*/
|
|
76
|
+
_saveToStorage() {
|
|
77
|
+
if (this.storage) {
|
|
78
|
+
if (typeof this.cacheOptions.cacheKey === "string") {
|
|
79
|
+
this.storage.setItem(this.cacheOptions.cacheKey, JSON.stringify(this.cache));
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* 设置缓存数据
|
|
85
|
+
* @param params 缓存的参数
|
|
86
|
+
* @param data 要缓存的数据
|
|
87
|
+
* @param cacheOptions 可选的缓存配置,可以覆盖默认的缓存时间
|
|
88
|
+
*/
|
|
89
|
+
setCache(params, data, cacheOptions) {
|
|
90
|
+
const { cacheTime, cacheKeyEquals = defaultEquals.default } = {
|
|
91
|
+
...this.cacheOptions,
|
|
92
|
+
...cacheOptions
|
|
157
93
|
};
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
94
|
+
const cacheItemIndex = this.cache.findIndex((item) => {
|
|
95
|
+
return cacheKeyEquals(item.params, params);
|
|
96
|
+
});
|
|
97
|
+
if (cacheItemIndex > -1) {
|
|
98
|
+
this.cache.splice(cacheItemIndex, 1);
|
|
99
|
+
}
|
|
100
|
+
this.cache.push({
|
|
101
|
+
params,
|
|
102
|
+
data,
|
|
103
|
+
expireTime: dateFns.addSeconds(/* @__PURE__ */ new Date(), cacheTime ?? 0).toISOString()
|
|
104
|
+
});
|
|
105
|
+
this._saveToStorage();
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* 获取缓存数据
|
|
109
|
+
* @param params 查询参数
|
|
110
|
+
* @returns 如果找到有效的缓存数据则返回数据,否则返回 null
|
|
111
|
+
*/
|
|
112
|
+
getCache(params) {
|
|
113
|
+
const itemIndex = this.cache.findIndex((item2) => {
|
|
114
|
+
return this.cacheOptions.cacheKeyEquals(item2.params, params);
|
|
115
|
+
});
|
|
116
|
+
const item = this.cache[itemIndex];
|
|
117
|
+
if (item) {
|
|
118
|
+
if (dateFns.isAfter(dateFns.parseISO(item.expireTime), /* @__PURE__ */ new Date())) {
|
|
119
|
+
return item.data;
|
|
120
|
+
} else {
|
|
121
|
+
this.cache.splice(itemIndex, 1);
|
|
164
122
|
this._saveToStorage();
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* 清空所有缓存数据
|
|
129
|
+
* 清空内存中的缓存数组并同步到存储中
|
|
130
|
+
*/
|
|
131
|
+
clear() {
|
|
132
|
+
this.cache = [];
|
|
133
|
+
this._saveToStorage();
|
|
134
|
+
}
|
|
135
|
+
}
|
|
169
136
|
exports.StorageMap = StorageMap;
|
|
170
137
|
exports.default = Cache;
|