构建一个可用的内存缓存.
Last active
December 21, 2017 03:57
-
-
Save axetroy/98dc3d3cc669879a31aea850be753a7d to your computer and use it in GitHub Desktop.
cache初稿
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const defaultConfig = { | |
MaximumCache: 100000 // 最大缓存个数, 如果缓存超出这个, 则会把最早的缓存删除掉 | |
}; | |
class Granule { | |
constructor(id, data) { | |
const now = new Date(); | |
this.id = id; // 数据id | |
this.data = data; // 数据 | |
this.createdAt = now; // 创建时间 | |
this.updatedAt = now; // 更新时间 | |
this.expiredAt = now; // 过期时间 | |
this.recentlyUsedAt = now; // 最近使用时间 | |
this.usageCount = 0; // 使用次数 | |
} | |
get isExpired() { | |
return new Date().getTime() - this.expiredAt.getTime() > 0; | |
} | |
} | |
class Cache { | |
constructor(config = defaultConfig) { | |
this.config = config; | |
this.map = new Map(); | |
this.tick = 0; | |
} | |
/** | |
* 添加缓存 | |
* @param id 缓存id | |
* @param data 缓存对象 | |
* @param expiration 过期时间 | |
* @returns {Cache} | |
*/ | |
add(id, data, expiration) { | |
if (this.length >= this.config.MaximumCache) { | |
for (let key of this.map.keys()) { | |
this.map.delete(key); | |
break; | |
} | |
} | |
const granule = new Granule(id, data); | |
granule.expiredAt = new Date(expiration); | |
this.map.set(id, granule); | |
} | |
/** | |
* remove cache | |
* @param id | |
*/ | |
remove(id) { | |
this.map.delete(id); | |
} | |
get length() { | |
return this.map.size; | |
} | |
/** | |
* clear cache | |
*/ | |
clear() { | |
this.map.clear(); | |
} | |
/** | |
* Get cache from an given id | |
* @param id | |
* @returns {*} | |
*/ | |
get(id) { | |
const element = this.map.get(id); | |
if (!element) { | |
return void 0; | |
} | |
const granule = element; | |
// 过期返回undefined, 并且删除缓存 | |
if (granule.isExpired) { | |
this.map.delete(id); | |
return void 0; | |
} | |
granule.recentlyUsedAt = new Date(); | |
granule.usageCount++; | |
if (this.tick === 10000) { | |
this.tick = 0; | |
} else { | |
this.tick++; | |
} | |
if (this.tick % 100 === 0) { | |
// 检查过期 | |
for (let g of this.map.values()) { | |
if (g.isExpired) { | |
this.remove(g.id); | |
} | |
} | |
} | |
return granule.data; | |
} | |
} | |
module.exports = Cache; | |
const c = new Cache(); | |
for (let i = 0; i < 110; i++) { | |
c.add(i, i, new Date().getTime() + 3600 * 1000); | |
} | |
console.log(c); | |
console.log(c.length); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment