如何使用事件将mongodb逻辑排除在node.js请求处理程序之外 [英] How to use events keep mongodb logic out of node.js request handlers

查看:34
本文介绍了如何使用事件将mongodb逻辑排除在node.js请求处理程序之外的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在寻找一个程序包(或模式)来处理来自mongodb的事件,这样我就可以避免嵌套的回调,并将mongodb逻辑排除在请求处理程序之外.

I'm looking for a package (or pattern) to handle events from mongodb so I can avoid nested callbacks and keep mongodb logic out of my request handlers.

现在我有如下代码:

start-express.js(服务器)

start-express.js (server)

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( express-resource 请求处理程序)

require('./things-provider');

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

things-provider.js(处理mongodb查询)

things-provider.js (handles mongodb queries)

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请求.

I'd like to avoid passing my http response object to my database handler or (worse) handling my db request in my http response handler.

最近,我意识到我想做的是创建一个事件处理程序,该事件处理程序注册一个http请求/响应,并在处理和发送http响应之前等待数据库的响应(事件).

I recently realized that what I want to do is create an event handler that registers an http request/response and waits for a response (event) from database before processing and sending the http response.

这听起来好像是对node.js已经做的事情的很多重复.是否存在处理此用例的现有框架?

That sounds like a lot of duplication of what node.js already does though. Is there an existing framework that handles this use case?

推荐答案

这是我想出的解决方案.

Here's the solution I've come up with.

我使用了 mongojs ,它大大简化了mongodb接口-以灵活配置为代价-但它隐藏了mongodb驱动程序所需的嵌套回调.它还使语法更像mongo客户端.

I used mongojs which greatly simplifies the mongodb interface --at the cost of flexibility in configuration-- but it hides the nested callbacks the mongodb driver requires. It also makes the syntax much more like the mongo client.

然后,我将HTTP Response对象包装在一个闭包中,并将此闭包传递给回调中的mongodb查询方法.

I then wrap the HTTP Response object in a closure and pass this closure to the mongodb query method in a callback.

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

从本质上讲,它仍然只是将响应对象传递给数据库提供者,但是通过将其包装在知道如何处理响应的闭包中,可以将逻辑保留在我的数据库模块之外.

It is still essentially just passing the response object to the database provider, but by wrapping it in a closure that knows how to handle the response, it keeps that logic out of my database module.

一个小的改进是使用一个函数在我的请求处理程序之外创建一个响应处理程序闭包:

A slight improvement is to use a function to create a response handler closure outside my request handler:

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

        response.send(data);
    };
}

所以现在我的请求处理程序看起来像这样:

So now my request handler just looks like this:

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

我的MongoProvider看起来像这样:

And my MongoProvider looks like this:

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;

我还可以将MongoProvider扩展为特定集合,以简化API并进行其他验证:

I can also extend MongoProvider for specific collections to simplify the API and do additional validation:

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;

这篇关于如何使用事件将mongodb逻辑排除在node.js请求处理程序之外的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆