JavaScript - 等待/阻塞直到构造函数完全加载完成

3
我正在创建的 JavaScript API 具有以下结构:
var engine = new Engine({
    engineName: "TestEngine",
    engineHost: "localhost"
});

// I don't want to proceed to the next line until Engine is fully loaded
// But the following part of the API is immediately called before the above is loaded
engine.startCar(
    "car_name",
    "car_id"
);

"Engine"实例需要几秒钟来加载(1-2秒)。因此,在此期间不应调用engine.startCar

我该如何对构造函数(new Engine())进行内部更改,以使其在完全加载之前不返回实例?


4
在回调函数中运行它,例如,使用 Promises(https://github.com/promises-aplus/promises-spec)。 - Jared Farrish
1
或者返回一个Promise,并把调用engine.startCar作为一个延续。 - Matt Burland
3个回答

7

这是JavaScript中的一个标准问题。通常在进行AJAX请求时会发生,但基于超时的延迟具有相同的基本问题。

jQuery和大多数具有此类问题的库通过拥有一个最初的方法来解决此问题,该方法返回可用于说“当X完成时,请执行Y”的“deferred”或“promise”对象。

这最好通过示例来解释。如果您在Engine构造函数中执行以下操作:

function Engine(option) {
     var readyDeferred = new $.Deferred();
     this.ready = readyDeferred;
     window.setTimeout(1000, function() {
         readyDeferred.resolve();
     }
}

当你构建一个引擎时,你可以简单地执行以下步骤:
var engine = new Engine({...});
engine.ready.done(function() {
    // start your engines!
});

当然,由于客户端机器的时间不同,如果你能使用一些除了 window.setTimeout 以外的逻辑来触发你的 readyDeferred.resolve(); 就更好了。例如,当所有 AJAX 请求完成时触发它,这比任何特定的等待时间更可预测。

2
您可以这样做:
function Engine(options, callback){ 
    this.engineName = options.engineName; 
    this.engineHost = options.engineHost; 

    //Wait for something to finish before calling the callback 
    var me = this; 
    setTimeout(function(){ 
        callback(me); 
    }, 1000); 

    this.startCar = function(){
        console.log(this.engineName); 
    }
}; 

var engine = new Engine({ 
    engineName: "TestEngine",
    engineHost: "localhost"
}, function(engine){ 
        //Run callback code 
        engine.startCar(); 
    }); 

http://jsfiddle.net/tnpsfy62/1/


2
你真的在提倡使用 setTimeout 等待异步进程吗? - Evan Davis
1
这只是一个占位符示例,用于ajax响应。由于问题中没有定义,我们怎么知道他在等待什么呢? - html_programmer
1
setTimeout有什么问题吗?正如Kim所说,它非常适合基本示例,而且OP字面上说它“需要几秒钟才能加载(1-2秒)”。如果他们说“页面加载后”或“我的AJAX返回后”,那么一个好的答案将包括$(function(...$.ajax(...).done...但由于没有,setTimeout似乎完全有效。 - machineghost

1

试试这个:

function Engine (params) {  
    console.log("In engine constructor");  
    console.log("In engine constructor - all done");  
    setTimeout(myStartEngine, 100);  
}

var engine = new Engine({
    engineName: "TestEngine",
    engineHost: "localhost"
});

// I don't want to proceed to the next line until Engine is fully loaded  
// But the following part of the API is immediately called before the above is loaded  

function myStartEngine() {
    console.log("Starting engine");

    engine.startCar(
        "car_name",
        "car_id"
    );

    console.log("Starting engine - done");
}

输出:

In engine constructor    
In engine constructor - all done    
About to start engine    
Starting engine - done    

这里是JSFiddle链接的示例。

祝你好运。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接