/
Cache.ts
97 lines (89 loc) · 2.03 KB
/
Cache.ts
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
import type { Tag } from './types';
/**
* 缓存管理类
* @public
*/
export class Cache<V> {
constructor(
protected readonly cache = new Map<any, { value: V; tag?: Tag; expires: number }>(),
protected readonly tagMap = new Map<Tag, Set<string>>(),
) {}
/**
* 清理过期缓存
*/
clearDeadCache() {
const now = Date.now();
for (const [k, v] of this.cache.entries()) {
if (v.expires > now) continue;
this.delete(k);
}
}
/**
* 获取缓存
*/
get(key: any) {
const v = this.cache.get(key);
if (!v) return null;
const now = Date.now();
if (now > v.expires) {
this.delete(key);
return null;
}
return v.value;
}
/**
* 设置缓存
* @param key 键
* @param value 值
* @param {} cacheConfig
* @param [cacheConfig.timeout=5000] 过期时间,默认5秒
* @param cacheConfig.tag 标签,可通过标签移除缓存
*/
set(key: any, value: V, { timeout = 5 * 1000, tag }: { timeout?: number; tag?: Tag } = {}) {
if (tag) {
if (!this.tagMap.has(tag)) this.tagMap.set(tag, new Set());
(this.tagMap.get(tag) as Set<string>).add(key);
}
this.cache.set(key, { value, tag, expires: timeout + Date.now() });
this.clearDeadCache();
}
/**
* 删除缓存
*/
delete(key: any) {
const value = this.cache.get(key);
this.cache.delete(key);
if (value?.tag) {
const tagSet = this.tagMap.get(value.tag);
if (tagSet) {
tagSet.delete(key);
// 如果有空的set就清理掉这个tag
if (!tagSet.size) this.tagMap.delete(value.tag);
}
}
}
/**
* 通过tag删除缓存
*/
deleteByTag(tag: Tag) {
const keys = this.tagMap.get(tag);
keys?.forEach((key) => {
this.cache.delete(key);
});
this.tagMap.delete(tag);
}
/**
* 清理所有缓存
*/
clear() {
this.cache.clear();
}
/**
* 判断是否存在某个缓存
* @param key
* @returns {boolean}
*/
has(key: any): boolean {
return this.get(key) !== null;
}
}