У меня проблема с шаблоном singleton, который я реализовал в 'program.js':
var Program = (function() {
var _program; // Instance of program
// Constructor
function Program() {
if (typeof _program != "undefined") {
throw new Error("Program can only be instantiated once.");
}
this.run = false; // flag to allow for program exec
_program = this;
};
// Public methods
Program.prototype.init = function() {
// the run call is nested in 4 callbacks
callbackHell (
this.run = true;
);
};
Program.prototype.execute = function() {
if(this.run == true) {
// do stuff
}
};
Program.getProgram = function () {
if(typeof _program == "undefined")
{
return new this();
}
return _program;
};
// Return the constructor
return Program;
})();
В моем "main.js" я держу ссылку на загруженную программу и проверяю флаг запуска, чтобы разрешить выполнение. Выглядит так:
var program = null;
function initDemo() {
program = Program.getProgram();
program.init();
runDemo();
};
function runDemo() {
if(program != null && program.run) {
program.execute();
}
requestAnimationFrame(runDemo);
};
Если я выполню этот код в браузере Chrome, он никогда не достигнет вызова program.execute() в main.js. Ссылка на программу будет поддерживать флаг выполнения равным false, даже если он изменен в функции init(). Я проверил все это в отладчике. Я должен указать, что вызов this.run = true вложен в 4 обратных вызова. Через некоторое время я решил, что могу просто изменить флаг запуска глобальной ссылки программы в main.js с помощью функции init(). Поэтому вместо "this.run = true", "program.run = true". Это работает, и цикл запустит execute(). Однако это не тот стиль, который я использую из ООП. Что на самом деле происходит здесь? Это определенно связано с обратными вызовами: когда я положил 'this.run = true' из обратных вызовов в конце init(), флаг был изменен правильно, однако в неподходящее время выполнения программы.
Вероятно, ваши обратные вызовы в callbackHell
делают что-то асинхронно и есть задержка до того, как program.run
будет фактически установлен в true
, последовательность примерно такая:
program.init()
runDemo()
, здесь program.run
является false
и существуетprogram.run
становится true
Решение этого - сделать ваш runDemo
еще одним обратным вызовом, поэтому ваш основной код будет выглядеть так:
var program = null;
function initDemo() {
program = Program.getProgram();
program.init(runDemo);
};
function runDemo() {
if(program != null) {
program.execute();
}
requestAnimationFrame(runDemo);
};
Здесь вам вообще не нужен флаг program.run
, вместо этого вы просто запускаете свою демо изнутри "callbackHell":
Program.prototype.init = function(functionToRun) {
// the run call is nested in 4 callbacks
callbackHell (
functionToRun(); // instead of setting program.run
// we call the specified function
);
};
initDemo()
где-нибудь?