export interface Cache { value?: V timeoutId?: ReturnType time?: number alive?: number } const NOT_ALIVE = 0 export class Memory { private cache: { [key in keyof T]?: Cache } = {} private alive: number constructor(alive = NOT_ALIVE) { // Unit second this.alive = alive * 1000 } get getCache() { return this.cache } setCache(cache) { this.cache = cache } // get(key: K) { // const item = this.getItem(key); // const time = item?.time; // if (!isNil(time) && time < new Date().getTime()) { // this.remove(key); // } // return item?.value ?? undefined; // } get(key: K) { return this.cache[key] } set(key: K, value: V, expires?: number) { let item = this.get(key) if (!expires || (expires) <= 0) expires = this.alive if (item) { if (item.timeoutId) { clearTimeout(item.timeoutId) item.timeoutId = undefined } item.value = value } else { item = { value, alive: expires } this.cache[key] = item } if (!expires) return value const now = new Date().getTime() /** * Prevent overflow of the setTimeout Maximum delay value * Maximum delay value 2,147,483,647 ms * https://developer.mozilla.org/en-US/docs/Web/API/setTimeout#maximum_delay_value */ item.time = expires > now ? expires : now + expires item.timeoutId = setTimeout( () => { this.remove(key) }, expires > now ? expires - now : expires, ) return value } remove(key: K) { const item = this.get(key) Reflect.deleteProperty(this.cache, key) if (item) { clearTimeout(item.timeoutId) return item.value } } resetCache(cache: { [K in keyof T]: Cache }) { Object.keys(cache).forEach((key) => { const k = key as any as keyof T const item = cache[k] if (item && item.time) { const now = new Date().getTime() const expire = item.time if (expire > now) this.set(k, item.value, expire) } }) } clear() { Object.keys(this.cache).forEach((key) => { const item = this.cache[key] item.timeoutId && clearTimeout(item.timeoutId) }) this.cache = {} } }