Há 3 pontos-chave para entender aqui e, em seguida, vou explicá-los em detalhes.
- module.exports é um objeto e os objetos são passados por cópia de referência em JavaScript.
- requer é um síncrono função.
- client.connect é um assíncrono função.
Como você sugeriu, é uma questão de tempo. node.js não pode saber que module.exports vai mudar mais tarde. Isso não é problema. Como saberia disso?
Quando
require
é executado, ele encontra um arquivo que atende aos seus requisitos com base no caminho que você digitou, lê-o e executa-o e armazena em cache module.exports para que outros módulos possam require
o mesmo módulo e não precisa reinicializá-lo (o que atrapalharia o escopo da variável, etc.) client.connect é uma chamada de função assíncrona, então depois de executá-la, o módulo termina a execução e o
require
call armazena uma cópia da referência module.exports e a retorna para users.js. Então você define module.exports = db
, mas é muito tarde. Você está substituindo a referência module.exports por uma referência a db, mas a exportação do módulo no nó require
cache está apontando para o objeto antigo. É melhor definir module.exports como uma função que obterá uma conexão e a passará para uma função de retorno de chamada assim:
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);
}
}
)
};
Aviso:embora esteja fora do escopo desta resposta, tenha muito cuidado com o código acima para garantir que você feche/retorne as conexões adequadamente, caso contrário, você vazará conexões.