【问题标题】:How can a module in node.js maintain state?node.js 中的模块如何维护状态?
【发布时间】:2014-05-06 18:10:38
【问题描述】:

我有两个使用相同模块的不同 js 文件。

file1.js:

var mod1 = require('commonmodule.js');
mod1.init('one');

file2.js:

var mod2 = require('commonmodule.js');
mod2.init('two');

(这两个文件file1.js,file2.js都加载在我的server.js文件中,它们本身就是模块)

现在在 commonmodule.js 中:

var savedName;
exports.init = function(name)
{
    savedName = name;
}
exports.getName = function()
{
    return savedName;
}

我注意到这个 savedName 总是被覆盖,这取决于最后设置它的人。所以它似乎不起作用。我如何获得一个模块来维护状态?

注意:我也尝试在 commonmodule.js 中将 savedName 设置为exports.savedName 但它也不起作用

【问题讨论】:

  • 不,因为模块被缓存,所以任何更改都会在任何地方生效。那你的问题是什么?如何解决?为什么?
  • 是的,我想知道如何在模块内维护状态
  • 这就是maintained的状态。也许您想问如何为每个模块获取隔离状态?
  • 模块实际上是 IIFE,并且您定义的变量是 IIFE 闭包的一部分。 @miguel-mota 的解决方案适用于您的方案,因为该变量已在 CommonModule 函数中定义,因此是该函数闭包的一部分。

标签: javascript node.js


【解决方案1】:

您可以在每次需要模块时创建一个新实例:

commonmodule.js

function CommonModule() {
    var savedName;
    return {
        init: function(name) {
            savedName = name;
        },
        getName: function() {
            return savedName;
        }
    };
}

module.exports = CommonModule;

file1.js

var mod1 = new require('./commonmodule')();
mod1.init('one');
console.log(mod1.getName()); // one

file2.js

var mod2 = new require('./commonmodule')()
mod2.init('two');
console.log(mod2.getName()); // two

【讨论】:

  • 为什么需要“new”关键字?如果我错了,请纠正我,但函数不存储状态但直接对象存储。所以每次运行函数时都会返回一个新的对象。
  • @CarlosMiguelColanta 你说得对,这个例子中不需要new 关键字。如果你使用this 或 ES6 类来维护状态,那么它是必需的
【解决方案2】:

模块本身就是简单的对象实例。单个实例将由所有其他模块共享(需要注意的是它是通过相同的路径加载的)。如果需要状态,请使用类并导出构造函数。

示例:

//Person.js
function Person(name) {
    this.name = name;
}

module.exports = Person;

使用它:

var Person = require("./Person");
var bob = new Person("Bob");

【讨论】:

    【解决方案3】:

    模块不像类/类函数;默认情况下,mod1mod2 由于缓存而引用相同的模块。要跟踪每个实例的状态,您需要在模块中使用构造函数或类似的东西,例如

    var mod = require('commonmodule.js');
    var state = new mod.init('one');
    

    init 定义有状态对象。你也可以让它返回一个对象文字,在这种情况下你不必使用new(例如var state = require('commonmodule.js').init('one');

    (这是假设您希望模块除了每个实例状态之外还有其他共享状态;如果不是这样,Peter Lyons 的方法会更简单。)

    【讨论】:

    • 所以我必须将这个“状态”传递给我在这个模块中使用的每个函数,对吧? (因为模块取决于状态)
    【解决方案4】:

    您也许可以从缓存中删除您的模块。像这样:

    file1.js:

    var mod1 = require('commonmodule.js');
    mod1.init('one');
    

    file2.js:

    delete require.cache[require.resolve(modulename)];
    
    var mod2 = require('commonmodule.js');
    mod2.init('two');
    

    但我觉得不是很方便和干净。

    但您也可以clone it 或制作一个小型代理。

    你也可以创建类:

    var savedName;
    exports.obj = {}
    exports.obj.prototype.init = function(name)
    {
        savedName = name;
    }
    exports.obj.prototype.getName = function()
    {
        return savedName;
    }
    

    然后:

    var mod2 = new (require('commonmodule.js'))();
    mod2.init('two');
    

    【讨论】:

      猜你喜欢
      • 2017-01-10
      • 1970-01-01
      • 1970-01-01
      • 2019-09-06
      • 2022-10-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多