开发者问题收集

Node.js,Mongo 查找并返回数据

2016-02-06
49405

我使用了 15 年的 VB6 和 MySql,现在才开始接触 node 和 mongo。我确定这不是我最终的程序会用到的,但我需要对如何调用另一个模块中的函数并返回结果有一个基本的了解。

我希望模块有一个函数来打开数据库,在集合中查找并返回结果。我可能还想在该模块中为其他集合添加几个函数。现在我需要它尽可能简单,我可以稍后添加错误处理程序等。我花了好几天时间尝试不同的方法,module.exports={… 围绕函数,没有它,.send,返回所有,但都没有成功。我理解它是异步的,因此程序可能在数据到达之前就已经通过了显示点。

以下是我尝试使用 Mongo 运行数据库 db1 和集合 col1 的操作。

Db1.js
var MongoClient = require('mongodb').MongoClient;
module.exports = {
    FindinCol1 : function funk1(req, res) {
    MongoClient.connect("mongodb://localhost:27017/db1", function (err,db) {
            if (err) {
                return console.dir(err);
            }
            var collection = db.collection('col1');
            collection.find().toArray(function (err, items) {
                    console.log(items);
                   // res.send(items);
                }
            );
        });
    }
};


app.js
a=require('./db1');
b=a.FindinCol1();
console.log(b);

Console.log(items) 在 'FindinCol1' 调用时有效,但 console.log(b)(返回 'undefined')无效,因此我没有得到返回值,或者在返回时将其粘贴。我读了几十篇帖子,看了几十个视频,但我仍然停留在这一点上。任何帮助都将不胜感激。

2个回答

如另一个答案中所述,此代码是异步的,您不能简单地在回调链(嵌套函数)中返回所需的值。您需要公开一些接口,以便您在获得所需值后向调用代码发出信号(因此,回调它们或回调)。

另一个答案中提供了一个回调示例,但还有一个绝对值得探索的替代选项: promises

模块不会返回您使用所需结果调用的回调函数,而是返回一个可以进入两种状态(已实现或已拒绝)的承诺。调用代码等待承诺进入这两种状态之一,当它进入时,将调用相应的函数。模块通过 解析拒绝 来触发状态更改。无论如何,这里有一个使用承诺的示例:

Db1.js:

// db1.js
var MongoClient = require('mongodb').MongoClient;
/*
node.js has native support for promises in recent versions. 
If you are using an older version there are several libraries available: 
bluebird, rsvp, Q. I'll use rsvp here as I'm familiar with it.
*/
var Promise = require('rsvp').Promise;

module.exports = {
  FindinCol1: function() {
    return new Promise(function(resolve, reject) {
      MongoClient.connect('mongodb://localhost:27017/db1', function(err, db) {
        if (err) {
          reject(err);  
        } else {
          resolve(db);
        }        
      }
    }).then(function(db) {
      return new Promise(function(resolve, reject) {
        var collection = db.collection('col1');
        
        collection.find().toArray(function(err, items) {
          if (err) {
            reject(err);
          } else {
            console.log(items);
            resolve(items);
          }          
        });
      });
    });
  }
};


// app.js
var db = require('./db1');
    
db.FindinCol1().then(function(items) {
  console.info('The promise was fulfilled with items!', items);
}, function(err) {
  console.error('The promise was rejected', err, err.stack);
});

现在,node.js mongodb 驱动程序的最新版本对承诺具有本机支持,您无需做任何工作来将回调包装在承诺中,如上所示。如果您使用的是最新的驱动程序,这是一个更好的示例:

// db1.js
var MongoClient = require('mongodb').MongoClient;
                       
module.exports = {
  FindinCol1: function() {
    return MongoClient.connect('mongodb://localhost:27017/db1').then(function(db) {
      var collection = db.collection('col1');
      
      return collection.find().toArray();
    }).then(function(items) {
      console.log(items);
      return items;
    });
  }
};


// app.js
var db = require('./db1');
    
db.FindinCol1().then(function(items) {
  console.info('The promise was fulfilled with items!', items);
}, function(err) {
  console.error('The promise was rejected', err, err.stack);
});

承诺为异步控制流提供了一种极好的方法,我强烈建议您花一些时间熟悉它们。

Emma
2016-02-06

是的,这是一个异步代码,使用 return 您将获得 MongoClient 对象或什么都得不到,具体取决于您放置的位置。

您应该使用回调参数:

module.exports = {
  FindinCol1 : function funk1(callback) {
    MongoClient.connect("mongodb://localhost:27017/db1", function (err,db) {
      if (err) {
        return console.dir(err);
      }
      var collection = db.collection('col1');
      collection.find().toArray(function (err, items) {
        console.log(items);       
        return callback(items);     
      });
    });
  }
};

将回调函数传递给 FindinCol1

a.FindinCol1(function(items) {
  console.log(items);
});

我建议您查看这篇文章: https://docs.nodejitsu.com/articles/getting-started/control-flow/what-are-callbacks

Gergo
2016-02-06