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
?
答案 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);
关于代码的说明:
Getters以及如何定义这些内容已有详细记录here。
立即调用的循环中的匿名函数是为了避免循环中的闭包问题。 (有关问题的完整讨论,请参阅this question。)
循环代码:
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下缓存的任何其他模块。
注意:我同意路易斯的观点,即你需要这样做的事实表明你可能需要采取不同的方式。