JavaScript Singleton теряет ссылку

1

У меня проблема с шаблоном 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(), флаг был изменен правильно, однако в неподходящее время выполнения программы.

  • 0
    Не видите, что вы вызываете initDemo() где-нибудь?
  • 0
    `if (typeof instance! =" undefined ") {` вы имеете в виду _program здесь?
Показать ещё 2 комментария
Теги:
callback
oop
singleton
reference

1 ответ

1
Лучший ответ

Вероятно, ваши обратные вызовы в 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
    );
};

Ещё вопросы

Сообщество Overcoder
Наверх
Меню