如何在不同路径需要时重新使用 Node.js 模块
How to re-use Node.js module when required with different paths
我有一个名为 counter 的自定义模块,它被多个其他模块使用。这些其他模块位于不同的目录中,这导致需要具有不同路径的 counter 模块。
下面是简化的设置。
- dir1
-- counter.js
-- module1.js
- dir2
-- module2.js
counter.js
var count = 0;
counter.increment = function(){
count++;
console.log(count);
};
module1.js
var counter = require('./counter');
counter.increment(); // Prints 1
module2.js
var counter = require('../dir1/counter')
counter.increment(); // Prints 1, but should print 2
如果使用相同的包含路径,那么 counter 只会被创建一次,并且相同的 counter 模块将被两者使用模块 1 和模块 2。但是因为 require 路径不同,所以创建了两个单独的 counter 模块。
有谁知道如何防止这种情况发生?我只想拥有一个 counter 模块。
发生这种情况是因为当您导入文件时,它会在那里创建一个新实例,因此在您的每个模块中它将以 0 开头。
解决方案是在主文件中将计数器作为全局导入并在所有地方使用相同的
在主文件中
global.counter = require('./counter');
在模块文件中
global.counter.increment();
计数器文件可以从任何文件、模块加载,这无关紧要。只需声明一次并确保在使用增量方法之前加载它。
因为你想要一个 per-app 单例并且 require()
无法知道具有两个独立路径的模块实际上是同一个模块,我知道的唯一方法是这样做(除了删除模块的单独路径)是让您的模块将一个单例注册为全局,然后在创建另一个单例之前对该单例进行自己的初始化检查。然后,每次加载它时,它只会 return 一个指向那个单例的导出。
// counter.js
// if no singleton yet, create the one singleton
if (!global._counter) {
global._counter = new Counter();
}
// export the singleton
module.exports = global._counter;
第一次使用 require()
加载(无论路径是什么),它将创建一个单例并将其存储在 global._counter
变量中。第二次加载时(即使路径不同),它会找到之前的单例并导出同一个单例。所以,永远只有一个计数器。
这让所有使用它的代码都将其视为一个真正的模块,并避免在此处以外的任何地方使用 global
引用。通常要避免使用全局变量,但是当您想要对某物进行单例引用并且不能使用模块级变量来保存它(这是您的确切情况)时,这是它们的好处之一。
然后,您就可以像普通模块一样使用它了:
var counter = require('./counter');
counter.increment(); // Prints 1
// in another file
var counter = require('../dir1/counter');
counter.increment(); // Prints 2
一个好的解决方案是只使 count 变量成为全局变量而不是使整个模块成为全局变量。例如-
在主文件中-
global.count=0;
在counter.js
counter.increment = function(){
count++;
console.log(count);
};
这样您就不需要更改 module1.js 和 module2.js,甚至可以像之前那样使用其他模块。
我在我的项目中使用 NODE_PATH
环境变量。它的价值是,项目的根源。然后要求本地模块变得像要求 npm
模块一样。
对于相同的设置,我更改了 require 语句:
下面是简化的设置。
- dir1
-- counter.js
-- module1.js
- dir2
-- module2.js
counter.js
var count = 0;
exports.increment = function(){
count++;
console.log(count);
};
module1.js
var counter = require('dir1/counter');
counter.increment(); // Prints 1
module2.js
var counter = require('dir1/counter')
counter.increment(); // Prints 2
我运行 带有NODE_ENV
环境变量的程序。
NODE_ENV=. node
> require('dir1/module1');
1
{}
> require('dir2/module2');
2
{}
>
.
表示当前文件夹。
我有一个名为 counter 的自定义模块,它被多个其他模块使用。这些其他模块位于不同的目录中,这导致需要具有不同路径的 counter 模块。
下面是简化的设置。
- dir1
-- counter.js
-- module1.js
- dir2
-- module2.js
counter.js
var count = 0;
counter.increment = function(){
count++;
console.log(count);
};
module1.js
var counter = require('./counter');
counter.increment(); // Prints 1
module2.js
var counter = require('../dir1/counter')
counter.increment(); // Prints 1, but should print 2
如果使用相同的包含路径,那么 counter 只会被创建一次,并且相同的 counter 模块将被两者使用模块 1 和模块 2。但是因为 require 路径不同,所以创建了两个单独的 counter 模块。
有谁知道如何防止这种情况发生?我只想拥有一个 counter 模块。
发生这种情况是因为当您导入文件时,它会在那里创建一个新实例,因此在您的每个模块中它将以 0 开头。
解决方案是在主文件中将计数器作为全局导入并在所有地方使用相同的
在主文件中
global.counter = require('./counter');
在模块文件中
global.counter.increment();
计数器文件可以从任何文件、模块加载,这无关紧要。只需声明一次并确保在使用增量方法之前加载它。
因为你想要一个 per-app 单例并且 require()
无法知道具有两个独立路径的模块实际上是同一个模块,我知道的唯一方法是这样做(除了删除模块的单独路径)是让您的模块将一个单例注册为全局,然后在创建另一个单例之前对该单例进行自己的初始化检查。然后,每次加载它时,它只会 return 一个指向那个单例的导出。
// counter.js
// if no singleton yet, create the one singleton
if (!global._counter) {
global._counter = new Counter();
}
// export the singleton
module.exports = global._counter;
第一次使用 require()
加载(无论路径是什么),它将创建一个单例并将其存储在 global._counter
变量中。第二次加载时(即使路径不同),它会找到之前的单例并导出同一个单例。所以,永远只有一个计数器。
这让所有使用它的代码都将其视为一个真正的模块,并避免在此处以外的任何地方使用 global
引用。通常要避免使用全局变量,但是当您想要对某物进行单例引用并且不能使用模块级变量来保存它(这是您的确切情况)时,这是它们的好处之一。
然后,您就可以像普通模块一样使用它了:
var counter = require('./counter');
counter.increment(); // Prints 1
// in another file
var counter = require('../dir1/counter');
counter.increment(); // Prints 2
一个好的解决方案是只使 count 变量成为全局变量而不是使整个模块成为全局变量。例如-
在主文件中-
global.count=0;
在counter.js
counter.increment = function(){
count++;
console.log(count);
};
这样您就不需要更改 module1.js 和 module2.js,甚至可以像之前那样使用其他模块。
我在我的项目中使用 NODE_PATH
环境变量。它的价值是,项目的根源。然后要求本地模块变得像要求 npm
模块一样。
对于相同的设置,我更改了 require 语句:
下面是简化的设置。
- dir1
-- counter.js
-- module1.js
- dir2
-- module2.js
counter.js
var count = 0;
exports.increment = function(){
count++;
console.log(count);
};
module1.js
var counter = require('dir1/counter');
counter.increment(); // Prints 1
module2.js
var counter = require('dir1/counter')
counter.increment(); // Prints 2
我运行 带有NODE_ENV
环境变量的程序。
NODE_ENV=. node
> require('dir1/module1');
1
{}
> require('dir2/module2');
2
{}
>
.
表示当前文件夹。