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 getAThing
accept a callback function as a parameter and then call that function once thing
is 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
/await
now 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 async
function as let thing = await getAThing();
.
然后您可以从另一个async
函数调用它作为let thing = await getAThing();
.
However, it's worth noting that MongoClient
provides a connection pool, so you shouldn't be opening and closing it within this method. Instead, call MongoClient.connect
during 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 await
within 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
您可以使用异步/等待
await
operator pauses the execution of asynchronous function until the Promise is resolved and returns the value.
await
operator 暂停异步函数的执行,直到 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
- 您可以使用任何异步库编写类似“同步”的代码
- 错误是从回调中抛出的,这意味着您不需要成功检查
- 您可以将结果作为承诺传递给任何其他代码