Javascript 在 Node.js 中进行同步 MongoDB 查询的正确方法是什么?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/12030248/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
What is the right way to make a synchronous MongoDB query in Node.js?
提问by Mike Pateras
I'm using the Node.JS driver for MongoDB, and I'd like to perform a synchronous query, like such:
我正在为 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;
});
});
}
});
});
}
The problem is, db.open is an asychronous call (it doesn't block), so the getAThing returns "undefined" and I want it to return the results of the query. I'm sure I could some sort of blocking mechanism, but I'd like to know the right way to do something like this.
问题是,db.open 是一个异步调用(它不会阻塞),所以 getAThing 返回“未定义”,我希望它返回查询的结果。我确信我可以采用某种阻止机制,但我想知道做这样的事情的正确方法。
采纳答案by JohnnyHK
There's no way to make this synchronous w/o some sort of terrible hack. The right way is to have getAThingaccept a callback function as a parameter and then call that function once thingis available.
没有办法在没有某种可怕的黑客攻击的情况下使这种同步。正确的方法是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);
});
});
}
});
});
}
Node 7.6+ Update
节点 7.6+ 更新
async/awaitnow provides a way of coding in a synchronous stylewhen using asynchronous APIs that return promises (like the native MongoDB driver does).
async/await现在提供了一个同步编码的方式风格使用异步API,这些API返回的承诺(如本地的MongoDB驱动程序一样)时。
Using this approach, the above method can be written as:
使用这种方法,上面的方法可以写成:
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;
}
}
Which you can then call from another asyncfunction as let thing = await getAThing();.
然后您可以从另一个async函数调用它作为let thing = await getAThing();.
However, it's worth noting that MongoClientprovides a connection pool, so you shouldn't be opening and closing it within this method. Instead, call MongoClient.connectduring your app startup and then simplify your method to:
然而,值得注意的是它MongoClient提供了一个连接池,所以你不应该在这个方法中打开和关闭它。相反,MongoClient.connect在您的应用程序启动期间调用,然后将您的方法简化为:
async function getAThing() {
return db.collection("Things").findOne({ name: "bob" });
}
Note that we don't call awaitwithin the method, instead directly returning the promise that's returned by findOne.
请注意,我们不在await方法内调用,而是直接返回由findOne.
回答by Amol M Kulkarni
ES 6(Node 8+)
ES 6(节点 8+)
You can utilize async/await
您可以使用异步/等待
awaitoperator pauses the execution of asynchronous function until the Promise is resolved and returns the value.
awaitoperator 暂停异步函数的执行,直到 Promise 被解析并返回值。
This way your code will work in synchronous way:
这样您的代码将以同步方式工作:
const query = MySchema.findOne({ name: /tester/gi });
const userData = await query.exec();
console.log(userData)
较旧的解决方案 - 2013 年 6 月;)
Now the Mongo Syncis available, this is the right way to make a synchronous MongoDB query in Node.js.
现在Mongo Sync可用了,这是在 Node.js 中进行同步 MongoDB 查询的正确方法。
I am using this for the same. You can just write sync method like below:
我也在用这个。您可以编写如下同步方法:
var Server = require("mongo-sync").Server;
var server = new Server('127.0.0.1');
var result = server.db("testdb").getCollection("testCollection").find().toArray();
console.log(result);
Note: Its dependent on the node-fiberand some issues are there with it on windows 8.
注意:它依赖于节点光纤,并且在 Windows 8 上存在一些问题。
Happy coding :)
快乐编码:)
回答by Hugheth
While it's not strictly synchronous, a pattern I've repeatedly adopted and found very useful is to use coand promisifyyield on asynchronous functions. For mongo, you could rewrite the above:
虽然它不是严格同步的,但我反复采用并发现非常有用的一种模式是在异步函数上使用co和promisifyyield。对于 mongo,您可以重写上述内容:
var query = co( function* () {
var db = new mongo.Db("mydatabase", server, {});
db = promisify.object( db );
db = yield db.open();
yield db.authenticate("myuser", "mypassword");
var collection = yield db.collection("Things");
return yield collection.findOne( { name : "bob"} );
});
query.then( result => {
} ).catch( err => {
} );
This means:
这意味着:
- You can write "synchronous"-like code with any asynchronous library
- Errors are thrown from the callbacks, meaning you don't need the success check
- You can pass the result as a promise to any other piece of code
- 您可以使用任何异步库编写类似“同步”的代码
- 错误是从回调中抛出的,这意味着您不需要成功检查
- 您可以将结果作为承诺传递给任何其他代码

