简体   繁体   English

JavaScript Singleton 丢失引用

[英]JavaScript Singleton losing reference

I have a problem with a singleton pattern that I have implemented in 'program.js':我在“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;
})();

In my 'main.js' I keep a reference to the loaded program and check for the run flag to allow execution.在我的“main.js”中,我保留对加载程序的引用并检查运行标志以允许执行。 Looks like this:看起来像这样:

var program = null;

function initDemo() {
    program = Program.getProgram();
    program.init();
    runDemo();
};

function runDemo() {
    if(program != null && program.run) {
        program.execute();
    }
    requestAnimationFrame(runDemo);
};

If I execute this code on a Chrome browser, it will never reach the program.execute() call in main.js.如果我在 Chrome 浏览器上执行此代码,它将永远不会到达 main.js 中的 program.execute() 调用。 The reference of program will keep the run flag to false, even it is changed in the init() function.程序的引用将保持运行标志为假,即使它在 init() 函数中更改。 I checked for all of this in the debugger.我在调试器中检查了所有这些。 I should point out that the 'this.run = true' call is nested in 4 callbacks.我应该指出 'this.run = true' 调用嵌套在 4 个回调中。 After a while I figured I could just change the run flag of the global reference of program in main.js with the init() function.过了一会儿,我想我可以使用 init() 函数更改 main.js 中程序的全局引用的运行标志。 So instead of 'this.run = true', 'program.run = true'.所以不是'this.run = true',而是'program.run = true'。 This works and the loop will run execute().这有效并且循环将运行 execute()。 However this is not the style I am used from OOP.然而,这不是我在 OOP 中使用的风格。 What is actually happening here?这里究竟发生了什么? It definitely has to do with the callbacks: when I put 'this.run = true' out of the callbacks at the end of init() the flag is changed correctly, however at the wrong time of the program execution.这肯定与回调有关:当我在 init() 结束时将 'this.run = true' 从回调中删除时,标志会正确更改,但是在程序执行的错误时间。

Probably your callbacks in the callbackHell are doing something asynchronously and there is a delay before program.run will actually be set to true , the sequence is approximately this:可能您在 callbackHell 中的callbackHell正在异步执行某些操作,并且在program.run实际设置为true之前存在延迟,序列大致如下:

  • You call program.init()你调用program.init()
  • Your callbacks start working你的回调开始工作
  • You call runDemo() , here program.run is false and it exists你调用runDemo() ,这里program.runfalse ,它存在
  • Callbacks finish their work and program.run becomes true回调完成它们的工作并且program.run变为true

The solution to that is to make your runDemo to be another callback, so your main code will look like this:解决方案是让你的runDemo成为另一个回调,所以你的主要代码将如下所示:

var program = null;

function initDemo() {
    program = Program.getProgram();
    program.init(runDemo);
};

function runDemo() {
    if(program != null) {
        program.execute();
    }
    requestAnimationFrame(runDemo);
};

Here you don't need the program.run flag at all, instead you just start your demo from inside the "callbackHell":在这里,您根本不需要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
    );
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM