JavaScript Singleton失去参考

时间:2017-10-26 09:36:48

标签: javascript oop callback reference singleton

我遇到了单例模式的问题,我在' program.js'中实现了:

event   sample  chrom    bp1    bp2    bp1_gene    bp2_gene    bp1_feature    bp2_feature    type    length    id    fpkm
1    A373R11    2L    2425901    2426025    intergenic    intergenic    intergenic    intergenic    INV    0.1    <NA>    0

在我的主#j;&#39;我保留对加载的程序的引用,并检查运行标志以允许执行。看起来像这样:

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;
})();

如果我在Chrome浏览器上执行此代码,它将永远不会到达main.js中的program.execute()调用。程序的引用将使run标志保持为false,即使它在init()函数中被更改。我在调试器中检查了所有这些。我应该指出&#39; this.run = true&#39; call嵌套在4个回调中。过了一会儿,我想我可以用init()函数改变main.js中程序全局引用的run标志。因此,而不是&#39; this.run = true&#39;,&#39; program.run = true&#39;。这有效,循环将运行execute()。然而,这不是我从OOP使用的风格。这里到底发生了什么?这肯定与回调有关:当我把&#39; this.run = true&#39;在init()结束时的回调中,标志被正确更改,但是在程序执行的错误时间。

1 个答案:

答案 0 :(得分:1)

callbackHell中的回调可能是异步执行的,并且在program.run实际设置为true之前有一段延迟,序列大致为:

  • 您致电program.init()
  • 您的回调开始工作
  • 您致电runDemo(),此处program.runfalse且存在
  • 回调完成工作,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标志,而只是从&#34; callbackHell&#34;内部开始演示:

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
    );
};