0

我正在为以下情况寻找一种简洁的方式来构建我的 node.js 代码。我想过使用 EventEmitters 来创建“工作流”类型的东西。此外,我还想过使用其中一个异步库,尽管没有考虑到这一点。

问题:寻找一条数据

  1. 检查缓存,如果找到返回
  2. 检查数据库,如果找到返回(存储在缓存中)
  3. 获取实时数据并返回,(存储在数据库中,缓存)

我使用下面的事件发射器快速模拟了一些东西。

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, ... 中做起来可能/更容易吗?记忆?

4

1 回答 1

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库(例如 aptly named async)来使代码更具可读性,但这仍然应该对调用者完全隐藏。

于 2012-07-27T07:17:05.003 回答