Ci sono 3 punti chiave da capire qui e poi li spiegherò in dettaglio.
- module.exports è un oggetto e gli oggetti vengono passati per copia di riferimento in JavaScript.
- require è un sincrono funzione.
- client.connect è un asincrono funzione.
Come hai suggerito, è una questione di tempismo. node.js non può sapere che module.exports cambierà in seguito. Non è un problema. Come fa a saperlo?
Quando require
viene eseguito, trova un file che soddisfa i suoi requisiti in base al percorso immesso, lo legge e lo esegue e memorizza nella cache module.exports in modo che altri moduli possano require
lo stesso modulo e non è necessario reinizializzarlo (il che rovinerebbe l'ambito delle variabili, ecc.)
client.connect è una chiamata di funzione asincrona, quindi dopo averlo eseguito, il modulo termina l'esecuzione e require
call memorizza una copia del riferimento module.exports e lo restituisce a users.js. Quindi imposti module.exports = db
, ma è troppo tardi. Stai sostituendo il riferimento module.exports con un riferimento a db, ma l'esportazione del modulo nel nodo require
la cache punta al vecchio oggetto.
È meglio definire module.exports come una funzione che otterrà una connessione e quindi la passerà a una funzione di callback in questo modo:
var mongodb = require("mongodb");
var client = mongodb.MongoClient;
module.exports = function (callback) {
client.connect('mongodb://host:port/dbname', { auto_reconnect: true },
function(err, db) {
if (err) {
console.log(err);
callback(err);
} else {
// export db as member of exports
callback(err, db);
}
}
)
};
Avviso:sebbene non rientri nell'ambito di questa risposta, fai molta attenzione con il codice sopra per assicurarti di chiudere/restituire le connessioni in modo appropriato, altrimenti perderai le connessioni.