Der er 3 nøglepunkter at forstå her, og så vil jeg forklare dem i detaljer.
- module.exports er et objekt, og objekter videregives ved copy-of-reference i JavaScript.
- require er en synkron funktion.
- client.connect er en asynkron funktion.
Som du foreslog, er det en timing-ting. node.js kan ikke vide, at module.exports vil ændre sig senere. Det er ikke det, der er problemet. Hvordan ville den vide det?
Når require
kører, finder den en fil, der opfylder dens krav baseret på den sti, du indtastede, læser den og udfører den og cacherer module.exports, så andre moduler kan require
det samme modul og ikke behøver at geninitialisere det (hvilket ville ødelægge variabel scoping osv.)
client.connect er et asynkront funktionskald, så når du har udført det, afslutter modulet eksekveringen og require
call gemmer en kopi af module.exports-referencen og returnerer den til users.js. Derefter indstiller du module.exports = db
, men det er for sent. Du erstatter module.exports-referencen med en reference til db, men moduleksporten i noden require
cachen peger på det gamle objekt.
Det er bedre at definere module.exports som en funktion, der får en forbindelse og derefter videregive den til en tilbagekaldsfunktion som sådan:
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);
}
}
)
};
Advarsel:selvom det er uden for dette svars omfang, skal du være meget forsigtig med ovenstående kode for at sikre, at du lukker/returnerer forbindelserne korrekt, ellers vil du lække forbindelser.