Модули Appcelerator и CommonJS (кеширование и циклические ссылки)

Здесь вещь:

Я использую способ CommonJS для того, чтобы сделать мое мобильное (iPhone/Android) приложение модульным. Не удивительно. Но есть одна вещь, на которую я просто не могу опустить голову.

CommonJS позволяет мне создавать приватные переменные STATIC, что позволяет мне легко создавать синглтоны. Это, я думаю, по крайней мере, потому, что содержимое файла, который получает 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;

I 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

Почему тогда круговые ссылки вроде следующего не работают? (Возможно, я уже сам это прокомментировал, напишите/ответьте на него, если хотите).

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)

Ответ 1

Я также использую модули CommonJS в Appcelerator Titanium для создания мобильного приложения. То, что я сделал для решения проблемы с циклической зависимостью, было следующим: если A и B являются 2 круговыми зависимыми модулями, требуйте (A) в B и наоборот, прежде чем вам действительно понадобится его использовать. В моем случае мне понадобился A внутри B только тогда, когда была нажата определенная кнопка, поэтому я вставил запрос (A) в B внутри прослушивателя событий нажатия кнопки. Надеюсь, что это поможет.