Skip to content

Instantly share code, notes, and snippets.

@HuangXiZhou
Created April 27, 2018 00:17
Show Gist options
  • Save HuangXiZhou/8e47a43d74326d01b24675f82d885039 to your computer and use it in GitHub Desktop.
Save HuangXiZhou/8e47a43d74326d01b24675f82d885039 to your computer and use it in GitHub Desktop.
JavaScript LruCache
class LruCache {
constructor(maxsize) {
this._cache = {}; // 缓存
this._queue = []; // 队列
this._maxsize = maxsize; // 最大值
// 如果最大值输入非法 默认无限大
if (!this._maxsize || !(typeof this._maxsize === 'number') || this._maxsize <= 0) {
this._maxsize = Infinity;
}
// 运行定时器,定时检查过期值
setInterval(() => {
this._queue.forEach((el, idx) => {
const key = el;
const insertTime = this._cache[key].insertTime;
const expire = this._cache[key].expire;
const curTime = +new Date();
// 如果存在过期时间且超期,移除数据
if (expire && curTime - insertTime > expire) {
this._queue.splice(idx--, 1);
delete this._cache[key];
}
});
}, 1000);
}
// 生成唯一索引
_makeSymbol(key) {
return Symbol.for(key);
}
// 更新队列
_update(queue, key) {
// 移除
queue.forEach((el, idx) => {
if (el === key) {
queue.splice(idx, 1);
}
});
// 前置
queue.unshift(key);
return queue;
}
// 插入数据
set(key, value, expire) {
key = this._makeSymbol(key); // 生成唯一索引
// 如果已经存在该值,则重新赋值
if (this._cache[key]) {
this._cache[key] = {
value,
expire,
insertTime: this._cache[key].insertTime
}
this._queue = this._update(this._queue, key); // 更新队列
} else {
// 如果不存在,则插入
this._cache[key] = {
value,
expire,
insertTime: +new Date()
}
// 索引置前
this._queue.unshift(key);
// 超出最大值,截断
while (this._queue.length > this._maxsize) {
const item = this._queue.pop(); // 尾截断
delete this._cache[item]; // 删除
}
}
}
// 获取数据
get(key) {
key = this._makeSymbol(key);
// 如果存在该值
if (this._cache[key]) {
const insertTime = this._cache[key].insertTime; // 插入时间
const expire = this._cache[key].expire; // 过期时间
const curTime = +new Date(); // 当前时间
// 如果不存在过期时间 或 存在过期时间但尚未过期
if (!expire || (expire && curTime - insertTime < expire)) {
// 更新队列,前置索引
this._queue = this._update(this._queue, key);
return this._cache[key].value;
} else if (expire && curTime - insertTime > expire) {
// 已经过期
this._queue.forEach((el, idx) => {
if (el === key) {
this._queue.slice(idx, 1);
delete this._cache[key];
}
})
return null
}
} else {
return null;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment