缓存异步Node.js对象,避免回调地狱

时间:2015-07-01 22:23:00

标签: javascript node.js caching q

我有一个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(也许是它对数据库的底层调用)来懒惰地加载/缓存结果,但是在我需要时仍然提供值,没有过多的嵌套回调结构/太多包装代码。

希望这是有道理的。如果没有,请告诉我,我会尽力澄清。

0 个答案:

没有答案