当在node.js中多次需要一个模块时,它会返回相同的对象,因为require()
会缓存之前的调用。
假设我有一个主记录器模块,可以注册子记录器模块。(这些通过主记录器模块的log()
函数实际进行日志记录。但这与此处无关。)
在主记录器模块中,我有类似以下内容以添加子模块:
module.addRedisLogger = function(rclient) {
modulesArray.push(require('./redis.js')(rclient, loggingEnabled, module));
}
当我创建一个redis客户端实例时,我可以立即像这样为其添加日志记录器:
var sub = redis.createClient();
logger.addRedisLogger(sub);
在子模块中,我开始像这样记录日志:
module.startLogging = function() {
rclient.on("message", messageCallback);
rclient.on("pmessage", pmessageCallback);
}
请停止这样记录日志:
module.stopLogging = function() {
rclient.removeListener("message", messageCallback);
rclient.removeListener("pmessage", pmessageCallback);
}
但据我所知,使用这种技术只能分配一个redis日志记录器实例,因为分配第二个将返回与第一个相同的
require()
对象,因此传递新的redis
参数将覆盖先前的值。因此,在第一个redis日志记录器实例中停止记录是不可能的,因为调用它会停止第二个实例中的记录。让我们看一个例子:
var sub1 = redis.createClient();
var sub2 = redis.createClient();
sub1.subscribe("joinScreen1");
sub2.subscribe("joinScreen2");
logger.addRedisLogger(sub1);
logger.addRedisLogger(sub2);
// running redis-cli PUBLISH joinScreen1 message1
// running redis-cli PUBLISH joinScreen2 message2
logger.log("Lets stop the first logger);
logger.modulesArray[0].stopLogging()
// running redis-cli PUBLISH joinScreen1 message1
// running redis-cli PUBLISH joinScreen2 message2
我期望你可以提供以下输出结果:
// Message received on channel joinScreen1: message1
// Message received on channel joinScreen2: message2
// Message received on channel joinScreen1: message1
我们应该得到这个,因为第一个记录器现在指向第二个实例。所以
redis
也指向了第二个客户端。但是我得到的是:
// Message received on channel joinScreen1: message1
// Message received on channel joinScreen2: message2
// Message received on channel joinScreen2: message2
所以它按照程序设计的预期工作,但不按照代码的预期工作。所以我想让它像现在这样工作,但我不明白为什么它会这样工作。
更新:
详细说明
module.js
var util = require("util");
module.exports = function () {
var module = {};
module.show = function() {
console.log(util.client);
}
module.set = function(value) {
util.client= value;
}
return module;
};
main.js
var util = require("util");
util.client = "waaaa";
var obj = require('./module')();
obj.show();
obj.set("weeee");
console.log(util.client);
运行
main.js
将会产生以下输出:C:\Users\me\Desktop>node main.js
waaaa
weeee
因此,require()
返回的对象与第一次相同。如果自那时起我进行了更改,则更改也会存在,因为它是相同的对象。
现在假设变量 redis
与这里的 client
相同,并保存对 redis 连接的引用。当构造函数第二次运行时,它将覆盖第一个构造函数,这就是为什么我希望从第一个 redis 客户端的记录器中获得通知,因为没有指向它的引用,因此无法删除监听器。