node.js通过数据缓存模式

时间:2012-07-27 05:42:16

标签: node.js design-patterns

我正在寻找一种干净的方法来构造我的node.js代码以用于以下情况。我想过使用EventEmitters创建一个“工作流”类型的东西。此外,我还想过使用其中一个异步库,但我们已经没有考虑过了。

问题: 寻找一块数据

  1. 检查缓存,如果找到则返回
  2. 检查db,如果找到则返回(存储在缓存中)
  3. 获取实时数据并返回(存储在db,cache中)
  4. 我使用下面的事件发射器快速模拟了一些东西。

    var util = require("util");
    var events = require('events');
    
    var CheckForData = function() {
        events.EventEmitter.call(this);
    
        this.checkForData = function(key) {
            this.emit("checkForDataRequest", key);
        }
    
        var _checkCache = function(key) {
            if (key === 'cache') {
                this.emit("found", {data:'cached data'});
            }
            else {
                console.log("not found in cache "+key);
                this.emit("checkDatastore", key);
            }
        }
    
        var _chechDatastore = function(key) {
            if (key === 'db') {
                this.emit("found", {data:'db data'});
                this.emit("storeCache", key, {data:'db data'});
            }
            else {
                console.log("not found in db "+key);
                this.emit("getData", key);
            }
        }
    
        var _getData = function(key) {
            if (key === 'live') {
                this.emit("found", {data:'live data'});
                this.emit("storeData", key, {data:'live data'});
            }
            else {
                console.log("not found in live "+key);
                this.emit("notFound", key);
            }
        }
    
        var _storeData = function(key, data) {
            this.emit("storeDb", key, data);
            this.emit("storeCache", key, data);
        }
    
        var _storeDb = function(key, data) {
            console.log("storing data in db. for "+key);
            console.log(data);
        }
    
        var _storeCache = function(key, data) {
            console.log("storing data in cache. for "+key);
            console.log(data);
        }
    
        var _found = function(data) {
            return data;
        }
    
        var _notFound = function(key) {
            return key;
        }
    
        this.on("checkForDataRequest", _checkCache);
        this.on("checkDatastore", _chechDatastore);
        this.on("getData", _getData);
        this.on("found", _found);
        this.on("notFound", _notFound);
        this.on("storeData", _storeData);
        this.on("storeDb", _storeDb);
        this.on("storeCache", _storeCache);
    };
    
    util.inherits(CheckForData, events.EventEmitter);
    module.exports = new CheckForData();
    

    测试它......

    var checkForData = require('./check-for-data');
    
    checkForData.on("found", function(data) {
        console.log("Found data ");
        console.log(data);
    });
    
    checkForData.on("notFound", function(key) {
        console.log("NOOO Found data for " + key);
    });
    
    console.log("-------");
    checkForData.checkForData('cache');
    console.log("-------");
    checkForData.checkForData('db');
    console.log("-------");
    checkForData.checkForData('live');
    console.log("-------");
    checkForData.checkForData('other');
    console.log("-------");
    

    然后async.js,我做了一个快速checkSeries,它基本上是async.detectSeries,但不是返回集合中的项目返回结果。见下文......

    var async = require('async');
    
    function check_cache(key) {
        console.log('checking cache');
        return null;
    }
    
    function check_datastore(key) {
        console.log('checking datastore');
        return null;//{data: "db data"};
    }
    
    function check_api(options) {
        console.log('calling api');
        return {data: "live data"};
    }
    
    function exists(item, callback) {
        callback(item());
    }
    
    async.checkSeries([check_cache, check_datastore, check_api], exists, function(result) {
        // result now equals the first function that return data
        console.log(result);
    });
    

    任何建议,提示,提示,......?我缺少一个模式或图书馆吗?你认为在Step,flow,......中有可能/更容易吗? memoize的?

1 个答案:

答案 0 :(得分:1)

这似乎为调用者和许多额外的代码做了很多工作,似乎没有增加太多价值。我的模型中有一些看起来像这样的东西。

Foo.get = function (id, cb) {

  var self = this;
  // check the cache first
  cache.get('foo:' + id, function (err, cacheFoo) {

    // if found, just return it
    if (!err && cacheFoo) {
      return cb(null, cacheFoo);
    }

    // otherwise get from db
    self.findOne({id: id}, function (err, dbFoo) {

      if (err || !dbFoo) {
        return cb(new Error('Foo not found', 404));
        // you could do get live call here
      }

      // and store in cache
      cache.store('foo:' + id, dbFoo);
      return cb(null, dbFoo);
    });
  });
};

然后,呼叫者可以随时调用Foo.get(id, callback),并且他们不必关心如何实际检索它。如果它变得更复杂,你可以使用async库(例如恰当命名的async)来使代码更具可读性,但这仍应完全隐藏在调用者之外。