-1

mongodb からのイベントを処理するパッケージ (またはパターン) を探しているので、ネストされたコールバックを回避し、mongodb ロジックを要求ハンドラーから除外できます。

現在、次のようなコードがあります。

start-express.js (サーバー)

var express = require('express');
var Resource = require('express-resource');
var app = express.createServer();

// create express-resource handler  which essentially does app.get('things', ...)
var things = app.resource('things', require('./things.js'));

app.listen(port);

things.js (エクスプレス リソースリクエスト ハンドラー)

require('./things-provider');

// handle request  'http://example.com/things'
exports.index = function(request, response) {
    sendThings(db, response);
};

things-provider.js (mongodb クエリを処理します)

var mongodb = require('mongodb')

// create database connection
var server = new mongodb.Server(host, port, {auto_reconnect: true});
var db = new mongodb.Db(dbName, server);

db.open(function (err, db) {
    if (err) { }
    // auto_reconnect will reopen connection when needed
});

function sendThings(db, response) {            
    db.collection('things', function(err, collection) {
        collection.find(function(err, cursor) {
            cursor.toArray(function(err, things) {
                response.send(things);
            });
        });
    });
}

module.exports.sendThings = sendThings;

http 応答オブジェクトをデータベース ハンドラーに渡したり、(さらに悪いことに) http 応答ハンドラーで db 要求を処理したりしたくありません。

最近、私がやりたいことは、http 要求/応答を登録し、http 応答を処理して送信する前にデータベースからの応答 (イベント) を待機するイベント ハンドラーを作成することであることに気付きました。

これは、node.js が既に行っていることと重複しているように思えます。このユースケースを処理する既存のフレームワークはありますか?

4

2 に答える 2

2

これが私が思いついた解決策です。

私はmongodbインターフェイスを大幅に簡素化するmongojsを使用しましたが、構成の柔軟性を犠牲にしていますが、mongodbドライバーが必要とするネストされたコールバックを隠しています。また、構文が mongo クライアントのようになります。

次に、HTTP 応答オブジェクトをクロージャーでラップし、このクロージャーをコールバックで mongodb クエリ メソッドに渡します。

var MongoProvider = require('./MongoProvider');
MongoProvider.setCollection('things');

exports.index = function(request, response){
    function sendResponse(err, data) {
        if (err) { 
            response.send(500, err);
        }    
        response.send(data);
    };

    MongoProvider.fetchAll(things, sendResponse);
};

基本的には応答オブジェクトをデータベース プロバイダーに渡すだけですが、応答を処理する方法を知っているクロージャーでラップすることで、そのロジックをデータベース モジュールから除外します。

わずかな改善は、関数を使用して、リクエスト ハンドラの外側でレスポンス ハンドラ クロージャを作成することです。

function makeSendResponse(response){
    return function sendResponse(err, data) {
        if (err) {
            console.warn(err);
            response.send(500, {error: err});
            return;
        }

        response.send(data);
    };
}

したがって、私のリクエストハンドラーは次のようになります。

exports.index = function(request, response) {
    response.send(makeSendResponse(response));
}

そして、私の MongoProvider は次のようになります。

var mongojs = require('mongojs');

MongoProvider = function(config) {
this.configure(config);
    this.db = mongojs.connect(this.url, this.collections);
}

MongoProvider.prototype.configure = function(config) {
    this.url = config.host + "/" + config.name;
    this.collections = config.collections;
}

MongoProvider.prototype.connect = function(url, collections) {
    return mongojs.connect(this.url, this.collections);
}

MongoProvider.prototype.fetchAll = function fetchAll(collection, callback) {
    this.db(collection).find(callback);
}

MongoProvider.prototype.fetchById = function fetchById(id, collection, callback) {
    var objectId = collection.db.bson_serializer.ObjectID.createFromHexString(id.toString());

    this.db(collection).findOne({ "_id": objectId }, callback);
}

MongoProvider.prototype.fetchMatches = function fetchMatches(json, collection, callback) {
    this.db(collection).find(Json.parse(json), callback);
}

module.exports = MongoProvider;

API を簡素化し、追加の検証を行うために、特定のコレクションの MongoProvider を拡張することもできます。

ThingsProvider = function(config) {
    this.collection = 'things';
    this.mongoProvider = new MongoProvider(config);
    things = mongoProvider.db.collection('things');
}

ThingsProvider.prototype.fetchAll = function(callback) {
    things.fetchAll(callback);
}

//etc...

module.exports = ThingsProvider;
于 2012-08-23T16:55:25.803 に答える
0

まず最初に、よく構造化されたアプリでは、まっすぐな mongo よりも Mongoose の方が使いやすいことが分かります。それはあなたを助けるかもしれません。

第二に、あなたがやろうとしていることは、すでにエクスプレスを使用しているので、ミドルウェア (アプリ レベルまたはルート レベル) を介して簡単に達成できると思います。または、クエリがパラメーターに基づいて異なる場合は、パラメーター フィルタリング。私が最後に見たパターンは次のようになります。

var User = mongoose.model("user'); // assumes your schema is previously defined

app.param('user_id', function(req,res,next, id){
   User.find(id, function(err,user){
      if(err) next(err);
      else { 
         req.user = user; 
         next();
      }
   });
}); 

まだいくつかの入れ子がありますが、あなたの例ほど悪くはなく、はるかに扱いやすいです。次に、「/profile」エンドポイントがあるとしましょう。次のようにできます。

app.get('/profile/:user_id', function(req,res){ res.render('profile', req.user); }
于 2012-08-15T19:47:43.613 に答える