我正在为MongoDB使用Node.JS驱动程序,我想执行一个同步查询,例如:
function getAThing() { var db = new mongo.Db("mydatabase", server, {}); db.open(function(err, db) { db.authenticate("myuser", "mypassword", function(err, success) { if (success) { db.collection("Things", function(err, collection) { collection.findOne({ name : "bob"}, function(err, thing) { return thing; }); }); } }); }); }
问题是,db.open是一个异步调用(它不会阻塞),因此getAThing返回“ undefined”,我希望它返回查询结果。我确定我可以使用某种阻止机制,但我想知道执行此类操作的正确方法。
没有办法使这种同步变得不可怕。正确的方法是getAThing接受回调函数作为参数,然后thing在可用时调用该函数。
getAThing
thing
function getAThing(callback) { var db = new mongo.Db("mydatabase", server, {}); db.open(function(err, db) { db.authenticate("myuser", "mypassword", function(err, success) { if (success) { db.collection("Things", function(err, collection) { collection.findOne({ name : "bob"}, function(err, thing) { db.close(); callback(err, thing); }); }); } }); }); }
节点7.6+更新
async/await现在提供了一种使用返回承诺的异步API(例如本机MongoDB驱动程序那样)时的同步 样式 编码方式。
async
await
使用这种方法,上面的方法可以写成:
async function getAThing() { let db = await mongodb.MongoClient.connect('mongodb://server/mydatabase'); if (await db.authenticate("myuser", "mypassword")) { let thing = await db.collection("Things").findOne({ name: "bob" }); await db.close(); return thing; } }
然后您可以从另一个async函数调用let thing = await getAThing();。
let thing = await getAThing();
但是,值得注意的是,它MongoClient提供了一个连接池,因此您不应该在此方法中打开和关闭它。相反,请MongoClient.connect在应用启动期间调用,然后将方法简化为:
MongoClient
MongoClient.connect
async function getAThing() { return db.collection("Things").findOne({ name: "bob" }); }
请注意,我们不在await方法中调用,而是直接返回由返回的promise findOne。
findOne