Il y a 3 points clés à comprendre ici et ensuite je les expliquerai en détail.
- module.exports est un objet et les objets sont passés par copie de référence en JavaScript.
- require est un synchrone fonction.
- client.connect est un asynchrone fonction.
Comme vous l'avez suggéré, c'est une question de timing. node.js ne peut pas savoir que module.exports va changer plus tard. Ce n'est pas ça le problème. Comment le saurait-il ?
Lorsque require
s'exécute, il trouve un fichier qui répond à ses exigences en fonction du chemin que vous avez entré, le lit et l'exécute, et met en cache module.exports afin que d'autres modules puissent require
le même module et ne pas avoir à le réinitialiser (ce qui gâcherait la portée des variables, etc.)
client.connect est un appel de fonction asynchrone, donc après l'avoir exécuté, le module termine son exécution et le require
call stocke une copie de la référence module.exports et la renvoie à users.js. Ensuite, vous définissez module.exports = db
, mais c'est trop tard. Vous remplacez la référence module.exports par une référence à db, mais le module export dans le nœud require
cache pointe vers l'ancien objet.
Il est préférable de définir module.exports comme une fonction qui obtiendra une connexion et la passera ensuite à une fonction de rappel comme ceci :
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);
}
}
)
};
Attention :bien que cela sorte du cadre de cette réponse, soyez très prudent avec le code ci-dessus pour vous assurer que vous fermez/rétablissez les connexions de manière appropriée, sinon vous perdrez des connexions.