How to refresh the requirejs module?

时间:2015-09-14 16:12:34

标签: javascript node.js requirejs js-amd

I have two module settingmap.js

var settingMap = {
    scWidth : [4000, 6000, 8000],
    scHeight : [5000, 7000, 9000],
    bxWidth : [100, 90, 80],
    bxHeight : [100, 90, 80],
    totalTime : [50, 40, 30],
    level : [1, 2, 3],
    boxColor : ['yellow', 'green', 'blue']
};

and setting.js

define(['settingmap', 'gamestatus'], function (settingMap, gamestatus) {

    var setting = {
    scWidth : settingMap.scWidth[gamestatus.levelIndex],
    scHeight : settingMap.scHeight[gamestatus.levelIndex],
    bxWidth : settingMap.bxWidth[gamestatus.levelIndex],
    bxHeight : settingMap.bxHeight[gamestatus.levelIndex],
    totalTime : settingMap.totalTime[gamestatus.levelIndex],
    level : settingMap.level[gamestatus.levelIndex],
    maxLevel : settingMap.level.length,
    boxColor : settingMap.boxColor[gamestatus.levelIndex]
    };

    return setting;

});

and I use the setting in some other module,

I will make gamestatus.levelIndex++

but I always got the old setting without gamestatus.levelIndex++.

How to refresh module setting?

2 个答案:

答案 0 :(得分:1)

scWidth定义为getter

var setting = {
    get scWidth () { 
        return settingMap.scWidth[gamestatus.levelIndex]; 
    }
};

每次想要获得gamestatus.levelIndex的值时,都会评估scWidth

在您当前的代码中,scWidth设置为一次值,除非您有其他直接分配给它的代码,否则不会更改。

理论上你可以“刷新”一个RequireJS模块,但我并不主张将这种方法用于你的目标。要做到这一点很复杂。

您已编辑了自己的问题,在settings中添加了一大堆其他值,这些值映射到settingMap中的值。很公平,这就是我的方式。在settings中定义 not 的所有字段都遵循settings.<name> - &gt;模式settingMap.<name>[gamestatus.levelIndex]然后运行一个循环来为遵循该模式的所有字段定义getter:

// Extend this list to all the fields that follow the pattern.
var fields = ["scWidth", "scHeight"];

for (var i = 0, field; (field = fields[i]); ++i) {
    (function (field) {
        Object.defineProperty(settings, field, {
            get: function () {
                return settingMap[field][gamestatus.levelIndex];
            }
        });
    })(field);
}

这是一段完整的代码,表明它有效:

var gamestatus = {
    levelIndex: 0
};

var settingMap = {
    "scWidth": [ "scWidth0", "scWidth1"],
    "scHeight": [ "scHeight0", "scHeight1"]
};

var settings = {
    // Any field that does not follow the pattern can be put here.
    maxLevel : settingMap.level.length
};

// Extend this list to all the fields that follow the pattern.
var fields = ["scWidth", "scHeight"];

for (var i = 0, field; (field = fields[i]); ++i) {
    (function (field) {
        Object.defineProperty(settings, field, {
            get: function () {
                return settingMap[field][gamestatus.levelIndex];
            }
        });
    })(field);
}

console.log(settings.scWidth);
console.log(settings.scHeight);
gamestatus.levelIndex++;
console.log(settings.scWidth);
console.log(settings.scHeight);

关于代码的说明:

  1. Getters以及如何定义这些内容已有详细记录here

  2. 立即调用的循环中的匿名函数是为了避免循环中的闭包问题。 (有关问题的完整讨论,请参阅this question。)

  3. 循环代码:

    for (var i = 0, field; (field = fields[i]); ++i) {
    

    可能是:

    for (var i = 0; i < fields.length; ++i) {
        var field = fields[i];
    

    这两种方法在功能上是等效的,只要fields不包含可以评估为false的值(这里就是这种情况)。

答案 1 :(得分:0)

以下是刷新节点模块的方法(将其从缓存中删除),以便在下次调用require时从文件系统中获取新模块。

使用require.resolve来获取require加载的模块的绝对路径。例如,让我们说你需要这样的模块:

var settings = require('./settings.js');

然后你可以从require cache中删除该模块,如下所示:

// Use require.resolve to get the full path of the module.
var modulePath = require.resolve('./settings.js');
// The full path is the key of the cached module on require.cache.
delete require.cache[modulePath];

现在您的模块已从缓存中删除。请记住,如果您需要的模块本身也需要其他模块,它们仍将被缓存。当我需要一个不需要任何其他模块的自定义模块时,这就是缓存的样子。

这是在从npm:

中简单地要求bluebird模块之后缓存的样子

正如您所看到的,只需要将蓝鸟加载到一堆模块中即可。在许多情况下这不是问题,但是如果您尝试重置的行为实际上在依赖关系树中更深,那么重新要求bluebird fresh可能会重新运行bluebird的代码,但是当bluebird需要时任何其他模块,它们将从模块缓存中返回。

如果需要清除依赖项及其整个树,请迭代缓存并使用正则表达式。

Object.keys(require.cache).forEach(function (key) {
  if (key.test(/.*\/projectName\/node\_modules\/moduleName\/.*$/)) {
    delete require.cache[key];
  }
});

在您尝试取消缓存的模块下项目的node_modules目录中的任何模块的需要缓存中查找。在上面的例子中,它将从缓存中删除bluebird模块以及在bluebird下缓存的任何其他模块。

注意:我同意路易斯的观点,即你需要这样做的事实表明你可能需要采取不同的方式。