我有一个Express应用程序依赖于一个存储JSON对象的数据库,该JSON对象将用作应用程序的主要配置对象。我想缓存这个对象,所以我不必继续去数据库查找它。但是,如果将新的配置对象插入到数据库中,并且让我的应用程序在没有重新启动的情况下获取新对象,我还想要一种使这个缓存对象无效的方法。最重要的是,我想在不深入回调的情况下完成所有这些工作
首先,这是代码的一个例子(这是设计的,所以不要担心数据库设计或它的前提 - 它不是真的)。假设可以为用户分配一个角色列表,这些角色存储在此“config”对象中:
// config.js
var config;
module.exports = function(cb) {
if(config != null) {
cb(config);
} else {
db.query('SELECT data FROM config', function(res) {
config = JSON.parse(res.data);
cb(config);
})
}
}
// users.js
var config = require('config');
var roles;
config(function(data) {
roles = data['User Roles']; // Cache roles for the lifetime of the application, but doesn't allow for invalidation
});
module.exports = {
get: function(id, cb) {
db.query('SELECT name, roleIds FROM user WHERE id = $1', [id], function(res) {
var userRoles = _.map(res.roleIds, function(roleId) {
return roles[roleId];
});
cb({
'name': res.name,
'roles': userRoles
});
});
}
};
当应用程序启动时,此代码会缓存users.js
中的用户角色定义,但是当我使用新的配置数据更新数据库时,我无法使缓存无效。我已经完成了这样一种情况,即我将get
函数的内容包含在config()
的调用中,但是我需要在代码中的许多地方做这个模式,它看起来很笨拙必须这样做。
我认为理想的情况是这样的(使用回调或承诺 - 我也没关系):
// users.js
var config = require('config');
module.exports = {
get: function(id, cb) {
db.query('SELECT name, roleIds FROM user WHERE id = $1', [id], function(res) {
var userRoles = _.map(res.roleIds, function(roleId) {
return config('User Roles')[roleId]; // This call would either use the cached version or call out to the DB
});
cb({
'name': res.name,
'roles': userRoles
});
});
}
};
似乎我正在努力解决的真正问题是同步性。我希望函数调用config
(也许是它对数据库的底层调用)来懒惰地加载/缓存结果,但是在我需要时仍然提供值,没有过多的嵌套回调结构/太多包装代码。
希望这是有道理的。如果没有,请告诉我,我会尽力澄清。