Appcelerator 和 CommonJS 模块(缓存和循环引用)



事情是这样的:

我正在使用CommonJS方式使我的移动(iPhone/Android)应用程序模块化。不足为奇。但有一件事我就是想不通。

CommonJS允许我创建静态私有变量,这让我可以轻松创建单例。我认为这至少是因为获得require() d的文件的内容只读取一次,然后每次都返回导出对象(仅初始化一次)。

但是当我创建如下所示的循环引用时,每次都会执行包含模块中的代码。

等。。。有趣的是,当我写这个问题时,我突然意识到require()调用都没有在下一个开始之前完成(因此下面演示了堆栈溢出)。

关于我是否走上正轨的任何想法?这里已经过了凌晨 5 点,所以就我而言,所有的赌注都:D了。

例子:

看到这段代码,它定义了一个单例:

/* Singleton.js */
exports.getSingleton = getSingleton;
function getSingleton(name) {
  if (!instance) {
    instance = new Thing(name);
  }
  return instance;
}
function Thing(name) {
  this.name = name;
}
var instance;

我这样require()这个文件:

var theFirstThing = require('Singleton').getSingleton('first');
Ti.API.info('first: ' + theFirstThing.name)
var possiblyAnotherOtherThing = require('Singleton').getSingleton('second');
Ti.API.info('second: ' + possiblyAnotherOtherThing.name);

输出为:

[DEBUG] loading: /path/to/sim/MyApp.app/app.js, resource: app_js
[DEBUG] loading: /path/to/sim/MyApp.app/Singleton.js, resource: Singleton_js
[INFO] first: first
[INFO] second: first

那么为什么像下面这样的循环引用不起作用呢?(我可能已经自己回答过了,如果你愿意,可以评论/回答)。

应用.js

require('Banana');

菠萝.js

require('Banana');

香蕉.js

require('Pineapple');

因为输出是这样的:

[DEBUG] loading: /path/to/simulator/MyApp.app/app.js, resource: app_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
/* etcetera (total of 15 times back and forth) */
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Banana.js, resource: Banana_js
[DEBUG] loading: /path/to/simulator/MyApp.app/Pineapple.js, resource: Pineapple_js
[ERROR] Script Error = Maximum call stack size exceeded. (unknown file)

我也在Appcelerator Titanium中使用CommonJS模块来构建移动应用程序。我为解决循环依赖问题所做的是这样的:如果 A 和 B 是 2 个循环依赖模块,则在 B 中 require(A),反之亦然,就在您实际需要使用它之前。就我而言,只有当某个按钮被单击时,我才需要在 B 中输入 A,因此我在按钮的单击事件侦听器内的 B 中放置了一个 require(A)。希望有帮助。

最新更新