Appcelerator和CommonJS模块(缓存和循环引用) [英] Appcelerator and CommonJS modules (caching and circular references)
问题描述
这是东西:
我正在使用CommonJS方式使我的移动(iPhone/Android)应用程序模块化.毫不奇怪.但是有一件事我只是无法理解.
I'm using the CommonJS way of making my mobile (iPhone/Android) application modular. No surprise there. But there's one thing that I just can't get my head around.
CommonJS让我创建STATIC私有变量,这使我可以轻松创建单例.至少我认为,这是因为获取require()
d的文件的内容仅读取一次,然后每次都返回导出对象(仅初始化一次).
CommonJS lets me create STATIC private variables, which lets me create singletons at ease. This, I think at least, is because the contents of a file that gets require()
d is read only once and then the exports object (which is initialized only once) is returned every time.
但是当我创建如下所示的循环引用时,所包含的模块内部的代码每次都会执行.
But when I create a circular reference as seen below, the code inside the included module is executed every time.
等待...
有趣的是,当我写这个问题时,我突然意识到对require()
的任何调用都不会在下一个调用开始之前完成(因此,下面显示的堆栈溢出).
Wait...
Funny thing is, while I'm writing this question, I suddenly realise that none of the calls to require()
finish before the next one starts (hence the stack overflow demonstrated below).
关于我是否在轨道上的任何想法?到这里已经是凌晨5点了,所以就我而言,所有赌注都关闭了:D.
Any thoughts on whether I'm on track or not? It's past 5 AM over here, so all bets are off as far as I'm concerned :D.
示例:
参见这段代码,它定义了一个单例:
See this piece of code, it defines a singleton:
/* 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
为什么为什么像下面这样的循环引用不起作用? (我本人可能已经对此回答了,如果您愿意,可以对此发表评论/回答.)
Why is it then that circular references like the following don't work? (I might have already ansered this myself, comment/answer on it if you like).
app.js
require('Banana');
Pinapple.js
require('Banana');
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,因此我在按钮的click事件监听器中的B中放置了require(A).希望有帮助.
I too am using CommonJS modules in Appcelerator Titanium to build a mobile app. What I did to resolve the circular dependency problem was this: if A and B are the 2 circularly-dependent modules, require(A) in B, and vice-versa just before you actually need to use it. In my case, I needed A inside B only when a certain button got clicked, so I put a require(A) in B inside the button's click event listener. Hope that helps.
这篇关于Appcelerator和CommonJS模块(缓存和循环引用)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!