Appcelerator and CommonJS modules (caching and circular references)
appcelerator, circular-reference, commonjs, titanium
Solution
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.
Problem
Here's the thing: 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 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. 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). 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. EXAMPLES: 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; ``` I `require()` this file as such: ``` var theFirstThing = require('Singleton').getSingleton('first'); Ti.API.info('first: ' + theFirstThing.name) var possiblyAnotherOtherThing = require('Singleton').getSingleton('second'); Ti.API.info('second: ' + possiblyAnotherOtherThing.name); ``` The Output is: ``` [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'); ``` Because the output is this: ``` [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) ```