Nodejs中一个cache的设计
Nodejs中一个cache的设计
var cache = {};
function getCache(key, dep) {
if (cache[key] == undefined) {
dep.call(null,function(err, list) {
cache[key] = list;
});
return cache[key];
} else {
return cache[key];
}
}
var data = getCache(“aa”,
function(cb) {
BlogModel.find({}, cb);
});
console.log(data);
本来是根据key去cache中查找,如果找不到,就执行BlogModel查数据然后放在cache中,因为异步的原因返回是undefined,但如果在cb写在getCache调用的代码里,嵌套就太深了,而且代码都一样,看有没有更好的办法</code></pre>
7 回复
在Node.js中设计一个缓存(Cache)机制时,需要考虑几个关键点:缓存的存储结构、缓存的更新策略、以及如何处理异步操作。你提供的代码已经是一个不错的起点,但是它存在一些问题,比如回调地狱(Callback Hell)和返回值的问题。
为了改进这一点,我们可以使用Promises或async/await来更好地管理异步操作,并且确保缓存逻辑更清晰和易于维护。以下是一个改进后的示例:
// 引入必要的模块
const util = require('util');
const BlogModel = require('./models/BlogModel'); // 假设你有一个BlogModel模型
// 将回调函数转换为Promise
const findAsync = util.promisify(BlogModel.find.bind(BlogModel));
// 缓存对象
const cache = {};
// 获取缓存的函数
async function getCache(key, fetchFn) {
if (!cache[key]) {
try {
cache[key] = await fetchFn();
} catch (err) {
console.error(`Error fetching data for key ${key}:`, err);
throw err;
}
}
return cache[key];
}
// 示例使用
(async () => {
const fetchData = async () => {
const result = await findAsync({});
return result;
};
try {
const data = await getCache('aa', fetchData);
console.log(data);
} catch (err) {
console.error('Failed to retrieve data:', err);
}
})();
解释:
- Promisification:我们使用
util.promisify
将BlogModel.find
方法转换为返回Promise的形式。这使得我们可以更容易地处理异步操作。 - 异步函数:
getCache
函数被定义为async
,这样可以使用await
关键字来等待异步操作完成。 - 缓存逻辑:在
getCache
函数中,我们检查缓存中是否已经存在指定键的数据。如果不存在,则调用fetchFn
函数获取数据并将其存储到缓存中。 - 错误处理:我们使用
try...catch
块来捕获并处理可能发生的错误。
这种方法不仅避免了回调地狱的问题,还使得代码更加清晰和易于理解。
var cache = {};
function getCache(key, dep, callback) {
if (!cache.hasOwnProperty(key)) {
dep.call(null,function(err, list) {
cache[key] = list;
callback(null, list);
});
} else {
callback(null, cache[key]);
}
}
getCache("aa", function (cb) {
BlogModel.find({}, cb);
}, function (err, data) {
console.log(data);
});
学习了,改装一下 就可以弄成redis缓存的那种样子。
我的页面上有多块缓存的数据,依次读出来一起render一个模板,如果写成回调的话, 两部分数据没法写个一个回调里面render一个模板的
不行的,object 的key 一多,性能马上就下去了。玩玩还可以,实际千万别这么搞。
var redis = require('redis');
var client = redis.createClient();
var cache = {}
cache.getKey = function(key, callback){
client.get(key, callback);
};
cache.setKey = function(key, val, callback){
client.set(key, val, function(err){
callback(err, val);
});
}
var getCache = function(key, dep, callback){
cache.getKey(key, function(err, replies){
if(err) return callback(err);
if(!replies) {
dep.call(null, function(err, val){
if(err) return callback(err);
cache.setKey(key, val, callback);
});
} else {
return callback(err, replies);
}
});
}
getCache('aa', function(cb){
cb(null, '123')
},function(err, data){
console.log(data);
});
redis缓存版本
在Node.js中设计一个缓存机制时,通常需要考虑缓存的更新、过期以及并发访问等问题。你当前的实现存在一些问题,例如异步回调导致的返回值问题。下面是一种改进方案,使用Promise来解决异步回调地狱(callback hell)的问题,并且更好地处理缓存逻辑。
示例代码
const LRU = require('lru-cache');
const cache = new LRU({ max: 500, maxAge: 1000 * 60 * 60 }); // 设置最大缓存数量和最大存活时间
function getCache(key, fetcher) {
return new Promise((resolve, reject) => {
if (cache.has(key)) {
resolve(cache.get(key));
} else {
fetcher()
.then(result => {
cache.set(key, result);
resolve(result);
})
.catch(reject);
}
});
}
// 使用示例
getCache("aa", () => {
return new Promise((resolve, reject) => {
BlogModel.find({}, (err, list) => {
if (err) reject(err);
else resolve(list);
});
});
}).then(data => {
console.log(data);
}).catch(err => {
console.error(err);
});
解释
- 引入LRU缓存库:
LRU
是一个高效的缓存库,可以方便地管理缓存大小和过期时间。 - 定义
getCache
函数:该函数接受一个键名和一个获取数据的函数作为参数。如果缓存中有对应的数据,则直接返回;否则,调用获取数据的函数并将结果存储在缓存中。 - 使用Promise:通过返回Promise,我们避免了回调地狱,使代码更易于阅读和维护。
- 示例使用:在调用
getCache
时,传入一个返回Promise的函数,这样可以在异步操作完成后正确地处理结果。
这种方法不仅解决了异步回调的问题,还使得缓存的管理和更新更加清晰和高效。