Каков правильный способ сделать синхронный запрос MongoDB в Node.js?
Я использую драйвер Node.JS для MongoDB, и я бы хотел выполнить синхронный запрос, например:
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", и я хочу, чтобы он возвращал результаты запроса. Я уверен, что я могу какой-то механизм блокировки, но я хотел бы знать, как правильно это сделать.
Ответы
Ответ 1
Невозможно сделать это синхронно без какого-либо ужасного взлома. Правильный способ состоит в том, чтобы 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);
});
});
}
});
});
}
Ответ 2
Теперь доступен Mongo Sync, это правильный способ сделать синхронный запрос MongoDB в Node.js.
Я использую это для того же самого. Вы можете просто написать метод синхронизации, как показано ниже:
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);
Примечание. Его зависимость от node -fiber, и некоторые проблемы возникают с ним в окнах 8.
Счастливое кодирование:)
Ответ 3
Хотя это не строго синхронно, шаблон, который я неоднократно принимал и нашел очень полезным, заключается в использовании co и promisify выход по асинхронным функциям. Для монго вы можете переписать выше:
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 => {
} );
Это означает:
- Вы можете написать "синхронный" код с любой асинхронной библиотекой
- Ошибки выбрасываются из обратных вызовов, то есть вам не нужна проверка успеха
- Вы можете передать результат как обещание любой другой части кода