Det finns tre viktiga punkter att förstå här och sedan kommer jag att förklara dem i detalj.
- module.exports är ett objekt och objekt skickas med copy-of-referens i JavaScript.
- require är en synkron funktion.
- client.connect är en asynkron funktion.
Som du föreslog är det en timinggrej. node.js kan inte veta att module.exports kommer att ändras senare. Det är inte det som är problemet. Hur skulle den veta det?
När require
körs, hittar den en fil som uppfyller dess krav baserat på sökvägen du angav, läser den och kör den och cachar module.exports så att andra moduler kan require
samma modul och inte behöva återinitiera den (vilket skulle förstöra variabel omfattning, etc.)
client.connect är ett asynkront funktionsanrop, så när du har kört det avslutar modulen exekveringen och require
call lagrar en kopia av module.exports-referensen och returnerar den till users.js. Sedan ställer du in module.exports = db
, men det är för sent. Du ersätter module.exports-referensen med en referens till db, men modulexporten i noden require
cachen pekar på det gamla objektet.
Det är bättre att definiera module.exports som en funktion som får en anslutning och sedan skicka den till en återuppringningsfunktion så här:
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);
}
}
)
};
Varning:även om det ligger utanför det här svaret, var mycket försiktig med koden ovan för att se till att du stänger/återställer anslutningarna på rätt sätt, annars kommer du att läcka anslutningar.