Qual è il modo giusto per creare una query MongoDB sincrona in Node.js?

Sto usando il driver Node.JS per MongoDB, e mi piacerebbe eseguire una query sincrona, come ad esempio:

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

Il problema è che db.open è una chiamata asincrona (non blocca), quindi il getAThing restituisce “undefined” e voglio che restituisca i risultati della query. Sono sicuro di poter avere una sorta di meccanismo di blocco, ma mi piacerebbe conoscere il modo giusto per fare qualcosa del genere.

Non c’è modo di rendere questo sincrono senza una sorta di attacco terribile. Il modo giusto è che getAThing accetti una funzione di callback come parametro e poi chiama quella funzione una volta che la thing è disponibile.

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

Aggiornamento nodo 7.6+

async / await ora fornisce un modo di codificare in uno stile sincrono quando si usano API asincrone che restituiscono promesse (come fa il driver MongoDB nativo).

Utilizzando questo approccio, il metodo sopra può essere scritto come:

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

Quale puoi chiamare da un’altra funzione async come let thing = await getAThing(); .

Tuttavia, vale la pena notare che MongoClient fornisce un pool di connessioni, quindi non dovresti aprirlo e chiuderlo con questo metodo. Invece, chiama MongoClient.connect durante l’avvio dell’app e quindi semplifica il tuo metodo per:

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

Si noti che non richiamiamo l’ await nel metodo, ma restituendo direttamente la promise restituita da findOne .

Ora è disponibile Mongo Sync , questo è il modo giusto per creare una query MongoDB sincrona in Node.js.

Sto usando questo per lo stesso. Puoi semplicemente scrivere il metodo di sincronizzazione come di seguito:

 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: dipende dal nodo-fibra e alcuni problemi ci sono con esso su Windows 8.

Felice codifica 🙂

Anche se non è strettamente sincrono, uno schema che ho ripetutamente adottato e trovato molto utile è quello di usare co e promettere risultati su funzioni asincrone. Per mongo, potresti riscrivere quanto sopra:

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

Questo significa:

  1. È ansible scrivere codice “sincrono” con qualsiasi libreria asincrona
  2. Gli errori vengono lanciati dai callback, il che significa che non è necessario il controllo del successo
  3. Puoi passare il risultato come promise a qualsiasi altro pezzo di codice