在回调函数范围之外检索MongoDB结果

时间:2016-10-28 23:21:55

标签: javascript node.js mongodb

我正在尝试通过MongoClient findOne方法(在r参数中)检索回调函数范围之外的文档。我怎样才能做到这一点?

也许我对Node.js使用MongoDB驱动程序的方法不合适。

function loadUser(name) {
    var result = {};

    function connection(err, db) {
        assert.equal(null, err);

        function callback(err, r) {
            assert.equal(null, err);
            db.close();
            result = r; // This does not work
        }
        db.collection('users').findOne({'user.name':name}, callback);
    }
    MongoClient.connect(url, connection);
    return result;
}

3 个答案:

答案 0 :(得分:1)

您执行此操作的方式,结果将不是正确的对象,因为它在MongoDB找到它并分配了值之前返回。

您应该执行以下操作:

function loadUser(name, cb) {

    function connection(err, db) {
        assert.equal(null, err);

        function callback(err, r) {
            assert.equal(null, err);
            db.close();
            cb(err, r) // user
        }
        db.collection('users').findOne({'user.name':name}, callback);
    }
    MongoClient.connect(url, connection);
    return;
}

loadUser的用法是:

loadUser("example", function(err, user){
   console.log(user);
   //Now do what you need with user
});

另请注意,如果您一直在搜索用户,最好只打开一次连接,并在应用程序终止后关闭它。

答案 1 :(得分:0)

您的结果'变量存在于loadUser函数的范围内。与MongoDB的交互将是异步​​的,因此当您的回调触发时,loadUser函数将完成并且结果变量将不再存在。

您只需将结果变量移动到全局范围即可。您可能希望稍微重构一下您的代码,以便回调通知等待结果的任何内容'回来。

答案 2 :(得分:0)

您可以使用EventEmitter来处理异步任务,这使得数据流更易于维护,尤其是在您需要执行大量条件任务时:

"use strict";

var MongoClient = require('mongodb').MongoClient;
const EventEmitter = require('events');

class MyEmitter extends EventEmitter {}

var url = 'mongodb://localhost:27017/myproject';

const myEmitter = new MyEmitter();

// connect to database
var db = MongoClient.connect(url, function(err, dbs) {

    if (err) {
        console.log(err);
        return;
    }
    console.log("Connected correctly to server");
    db = dbs;
    //get user when connected
    myEmitter.emit('getUser');
});

// getUser event
myEmitter.on('getUser', function() {

    db.collection('users').findOne({ 'user.name': "test" }, function callback(err, r) {
        if (err) {
            myEmitter.emit('processError', err);
        } else {
            myEmitter.emit('processResult', r);
        }
        db.close();
    });

});

// process result event
myEmitter.on('processResult', function(result) {
    //result received, process it here
    console.log("result : " + result);
});

// error event
myEmitter.on('processError', function(err) {
    //an error occured, process the error here
    console.log("error : " + err);
});