是否可以在node.js

时间:2015-09-28 11:35:52

标签: javascript node.js mongodb child-process

我想将MongoDB数据库作为child_process运行,因为某些数据库操作需要花费大量时间,我不希望应用程序的其余部分冻结。

我能够将数据库代码放入一个模块中,该模块通过child_process中的事件发射器进行响应和重新生成。

以下是简化版本中的代码(db-process.js):

var MongoClient = require('mongodb').MongoClient;
var url = 'mongodb://localhost:27017/myproject';
var db = null;

MongoClient.connect(url, function(err, database) {
    if(err){
        console.warn('Connection to MongoDB failed.');
    }else{
        db = database;
        console.log('Connected to MongoDB.');
    }
});   

process.on('message', function(msg) {
    switch(msg.name){
        case 'getRecord':   
            var collection = db.collection('SomeTable');
            collection.find({id: 'someId').toArray(function(err, docs) {
                if(!err) process.send{'name': 'getRecord', record: records[0]});
            });
            break;
        case 'saveRecord':
            // Code here...
            break;
    }
});

挑战在于我希望能够通过传递回调函数来使用数据库模块。这将使我更容易在我的所有其他模块中使用。但是如何将事件中的变量放入回调函数中呢?这甚至可能吗?

下面显示了我在简化版本(db-controller.js)中未完成的尝试:

var childProcess = require('child_process');
var dbProcess = childProcess.fork('./db-process.js');

dbProcess.on('message', function(msg) {
    switch(msg.name){
        case 'getRecord':
            var record = msg.record;
            break;
        case 'saveRecord':
            // Handling here...
            break;
    }
});    

var controller = {};    

controller.getRecord = function(onQueryDone){
    dbProcess.send({name: 'getRecord'});
    // How to call the callback function with data when it is received? Basicly want the record variable from the switch.
    onQueryDone(record);
};

controller.saveRecord = function(record, onQueryDone){
    dbProcess.send({name: 'saveRecord'});
    // Handling...
};

module.exports = controller;

所以我希望能够像这样使用这个模块:

var dbController = require('./db-controller.js');

dbController.getRecord(function(record)){
    // Do something with record...
});

有关如何实现这一目标的任何想法?

2 个答案:

答案 0 :(得分:0)

据我所知,您无法在节点实例(主实例和分叉实例)之间传递回调,但您可以传递数据。

您在案例中使用的是工作池模块,其中工作者实例将处理所有数据库查询,主服务器(池实例)将数据发送给这些工作人员并在完成后收集结果

这是我在github forked-worker-pool上提供的一个,但在npm还有其他一些选择。

答案 1 :(得分:0)

另一种选择是完全解耦您的流程。我之前在Amazon上使用过SQS,我将数据放入队列,还有另一个服务器/进程监听这些项目,唤醒并处理它们。这是一个非常简单的模型。如果您不在AWS上,您可能会使用像rabbitmq这样的东西。这样你的应用服务器永远不会被阻止,因为它只是将数据转储到队列并继续。