Как правильно сделать синхронный запрос MongoDB в узле.Яш?

Я использую узел.Драйвер 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", и я хочу, чтобы он вернул результаты запроса. Я уверен, что мог бы создать какой-то блокирующий механизм, но я хотел бы знать правильный способ сделать что-то вроде этого.

3 ответов


нет никакого способа сделать этот синхронный без какого-то ужасного взлома. Правильный путь-иметь 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 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;
    }
}

который вы можете затем позвонить из другого


теперь Mongo Sync доступно, это правильный способ сделать синхронный запрос MongoDB в узле.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);

Примечание: его иждивении узел-волокна и некоторые проблемы есть с ним в windows 8.

удачи в кодировании :)


хотя это не строго синхронно, шаблон, который я неоднократно принимал и нашел очень полезным, - использовать co и promisify выход на асинхронные функции. Для 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 => {

} );

Это значит:

  1. вы можете написать "синхронный" - подобный код с любой асинхронной библиотекой
  2. ошибки выбрасываются из обратных вызовов, что означает, что вам не нужна проверка успеха
  3. вы можете пройти результат как обещание любой другой части кода