Estoy usando el Node.JS driver de MongoDB, y me gustaría realizar un síncrona de consulta, tales como:

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;
                    });
                });
            }
        });
    });
}

El problema es, db.abierto es una de las asychronous llamada (no block), por lo que el getAThing devuelve «undefined» y quiero que se devuelven los resultados de la consulta. Estoy seguro de que podría algún tipo de mecanismo de bloqueo, pero me gustaría saber la manera correcta de hacer algo como esto.

InformationsquelleAutor Mike Pateras | 2012-08-19

3 Comentarios

  1. 19

    No hay manera de hacer que esto sincrónico w/o algún tipo de terrible hack. La manera correcta es tener getAThing aceptar una función de devolución de llamada como un parámetro y, a continuación, llamar a esa función una vez thing está disponible.

    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);
                        });
                    });
                }
            });
        });
    }

    Nodo 7.6+ Actualización

    async/esperan ahora proporciona una forma de codificación en un sincrónica estilo cuando el uso de Api asincrónicas que volver promesas (como los nativos de MongoDB controlador).

    Con este enfoque, el método anterior puede ser escrita como:

    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;
        }
    }

    Que se puede llamar de otra async función como let thing = await getAThing();.

    Sin embargo, vale la pena señalar que MongoClient proporciona una conexión de la piscina, por lo que no debe ser de apertura y cierre dentro de este método. En su lugar, llame a MongoClient.connect durante su aplicación de inicio y, a continuación, a simplificar su método:

    async function getAThing() {
        return db.collection("Things").findOne({ name: "bob" });
    }

    Nota que no llamamos a await dentro del método, en lugar de directamente de devolver la promesa que devuelve findOne.

    • Gracias Johnny por esta solución! Me gustaría que hubiera una manera simple fuera de la caja… es frustrante, incluso para escribir un simple if_exists() función… por Cierto, si alguien sabe una manera más fácil, o una actualización del controlador, por favor, publicarlo aquí.
    • Usted puede utilizar siempre un async biblioteca, para evitar la identation de «doom» github.com/caolan/async Que va a hacer el código más legible y agradable.
    • Yo no lo llamaría una «solución», que es como nodo está diseñado para trabajar.
    • si esta es la manera correcta de hacerlo … 🙁
    • regresó thing es un » objeto de la Promesa]’. ¿Cómo podemos interpretar los datos dentro de la promesa de objeto? (sin .then de devolución de llamada)
    • Usted puede await la promesa desde dentro de otra async función: let thing = await getAThing();
    • Estoy tratando de alejarse de la función de devolución de llamada modelo en el que es fácil manejar un error o éxito de resultado, es decir, function(err, result) { if (err) { res.send(err) } else { // do things } – ¿cómo manejar/vista un error que viene de vuelta de let thing = await db.collection.findOne(query)?
    • Con await tiene el uso de bloques try/catch para el manejo de errores.
    • como este? try { var bob = await getAThing() } catch(err) { console.log("mongodb query error is here: " + err ) }
    • Sí. Consulte here para más ejemplos.

  2. 30

    ES 6 (Nodo 8+)

    Puede utilizar async/await

    await operador se detiene la ejecución de la función asíncrona hasta que la Promesa se ha resuelto y devuelve el valor.

    De esta manera el código de trabajo de manera sincrónica:

    const query = MySchema.findOne({ name: /tester/gi });
    const userData = await query.exec();
    console.log(userData)


    Mayores De Solución De Junio De 2013 😉

    Ahora la Mongo Sync está disponible, esta es la forma correcta de hacer un síncrona de consulta en MongoDB Node.js.

    Estoy usando esto para el mismo. Sólo se pueden escribir método de sincronización, como el de abajo:

    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);

    Nota: Sus dependientes en el nodo de fibra de y algunos problemas existen en windows 8.

    Feliz de codificación 🙂

    • Lo programé un 5 de la línea de comandos con mongo-sync y fracasó, aunque coincidía con su código de prueba de casi perfectamente. Parece que tiene errores.
    • Puede usted por favor describa el problema exacto que usted tenía? debido a su trabajo para mí sin mayores problemas.. Si está seguro de que es un error en el módulo se puede plantear un nuevo tema en Repo
    • He presentado un error. Al parecer, usted tiene que eliminar las fibras de los módulos de node_modules en el mongo-sync lib. Se parece a un embalaje problema.
    • Si es dependiente en el nodo de fibra de entonces no es sincrónico
  3. 2

    Aunque no es estrictamente sincrónico, un patrón que he adoptó varias veces y muy útil es el uso de co y promisify rendimiento en funciones asincrónicas. Para mongo, se puede reescribir la anterior:

    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 => {
    
    } );

    Esto significa:

    1. Puede escribir «sincrónico»-como el código con cualquier asincrónica biblioteca
    2. Se generan errores de las devoluciones de llamada, lo que significa que usted no necesita el éxito de verificación
    3. Puede pasar el resultado como una promesa a cualquier otra pieza de código

Dejar respuesta

Please enter your comment!
Please enter your name here