node.js中require的行为 [英] Behavior of require in node.js

查看:77
本文介绍了node.js中require的行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前有一个包含以下内容的数据库连接模块:

I currently have a database connection module containing the following:

var mongodb = require("mongodb");
var client = mongodb.MongoClient;
client.connect('mongodb://host:port/dbname', { auto_reconnect: true },
      function(err, db) {
         if (err) {
            console.log(err);
         } else {
            // export db as member of exports
            module.exports.db = db;
         }
      }
);

然后我可以通过以下操作成功访问它:

I can then successfully access it doing the following:

users.js

var dbConnection = require("./db.js");
var users = dbConnection.db.collection("users");
users.find({name: 'Aaron'}).toArray(function(err, result) {
  // do something
});

但是,如果我改为导出module.exports = db,即尝试将exports对象分配给db对象而不是使其成为导出成员,然后尝试通过users.js中访问它>该对象未定义,为什么?

However, if I instead export module.exports = db, i.e., try to assign the exports object to the db object instead of making it a member of exports, and try to access it in users.js via var db = require("./db.js"); the object is undefined, why?

如果是因为建立连接存在延迟(require()不能等到模块完成其代码运行后再分配module.exports的值吗?),那么为什么这些示例都不起作用?

If it is because there is a delay in setting up the connection (shouldn't require() wait until the module finishes running its code before assigning the value of module.exports?), then why do neither of these examples work?

one.js

setTimeout(function() {
   module.exports.x = {test: 'value'};
}, 500);

two.js

var x = require("./one");
console.log(x.test);

OR

one.js

setTimeout(function() {
   module.exports.x = {test: 'value'};
}, 500);

two.js

setTimeout(function() {
   var x = require("./one");
   console.log(x.test);
}, 1000);

在两种情况下,运行$ node two.js都会打印undefined而不是value.

Running $ node two.js prints undefined in both cases instead of value.

推荐答案

这里有3个关键点需要理解,然后我将对其进行详细解释.

There are 3 key points to understand here and then I will explain them in detail.

  1. module.exports是一个对象,并且对象通过JavaScript中的引用复制传递.
  2. require是一个同步功能.
  3. client.connect是异步功能.
  1. module.exports is an object and objects are passed by copy-of-reference in JavaScript.
  2. require is a synchronous function.
  3. client.connect is an asynchronous function.

正如您所建议的,这是时机. node.js不知道module.exports将在以后更改.那不是问题.它怎么知道的?

As you suggested, it is a timing thing. node.js cannot know that module.exports is going to change later. That's not it's problem. How would it know that?

require运行时,它将根据您输入的路径找到一个满足其要求的文件,读取并执行该文件,并缓存module.exports,以便其他模块可以require使用同一模块,而不必重新初始化它(这会弄乱变量作用域,等等)

When require runs, it finds a file that meets its requirements based on the path you entered, reads it and executes it, and caches module.exports so that other modules can require the same module and not have to re-initialize it (which would mess up variable scoping, etc.)

client.connect是一个异步函数调用,因此在执行它之后,模块完成执行,并且require调用存储module.exports参考的副本并将其返回给users.js.然后设置module.exports = db,但是为时已晚.您正在用对db的引用替换module.exports引用,但是节点require缓存中的模块导出指向旧对象.

client.connect is an asynchronous function call, so after you execute it, the module finishes execution and the require call stores a copy of the module.exports reference and returns it to users.js. Then you set module.exports = db, but it's too late. You are replacing the module.exports reference with a reference to db, but the module export in the node require cache is pointing to the old object.

最好将module.exports定义为一个函数,该函数将获得连接,然后将其传递给回调函数,如下所示:

It's better to define module.exports as a function which will get a connection and then pass it to a callback function like so:

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);
             }
          }
    )
};

警告:尽管超出了此答案的范围,但是请对上面的代码非常小心,以确保正确关闭/返回连接,否则将泄漏连接.

Warning: though it's outside the scope of this answer, be very careful with the above code to make sure you close/return the connections appropriately, otherwise you will leak connections.

这篇关于node.js中require的行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆