0

次の状況でnode.jsコードを構造化するためのクリーンな方法を探しています。EventEmittersを使用して「ワークフロー」タイプのものを作成することを考えました。また、私はそこにある非同期ライブラリの1つを使用することを考えましたが、それはあまり考えられていませんでした。

問題:データを探す

  1. キャッシュをチェックし、見つかった場合はリターン
  2. dbをチェックし、見つかった場合はreturn(キャッシュに保存)
  3. ライブデータを取得して返す(dbに保存、キャッシュ)

以下のイベントエミッターを使用して、何かをすばやくモックアップしました。

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で、基本的にasync.detectSeriesであるクイックcheckSeriesを作成しましたが、コレクション内のアイテムを返す代わりに、結果を返します。下記参照...

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);
});

何か提案、ヒント、ヒント、...?欠落しているパターンまたはライブラリはありますか?ステップ、フロー、...で行うことが可能/簡単だと思いますか?メモ化?

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ライブラリ (適切な名前の などasync) を使用してコードを読みやすくすることができますが、これは呼び出し元から完全に隠されている必要があります。

于 2012-07-27T07:17:05.003 に答える