JavaScript异步回调 - 如何等待最终结果

时间:2013-05-29 09:31:40

标签: javascript asynchronous callback async-await setinterval

我有以下情况(另见jsFiddle - > http://jsfiddle.net/sMuWK/):

function CallBackStringHandler() {
    this.callback = function(){return null};
};

CallBackStringHandler.prototype.doTheMagic = function(callback) {
    var result = callback.call(this);
        if(result == null)
            alert("Nothing to handle yet...");
        else
            alert("End the result is: \n\n" + result);
};

function Action(){
    var result = null;
    var max = 10;
    var index = 0;
    var processor = setInterval(function(){
        if(index <= max){ //Processing step
            if(result == null)
                result = "" + index;
            else
                result += index;
            index++;
        } else { //Done
            clearInterval(processor);
            alert(result);
        }
    },10);
    return result;
};

function Run(){    
    var handler = new CallBackStringHandler();
    handler.doTheMagic(Action);
};

Run();

脚本(jQuery插件)允许您指定必须返回字符串的回调。 此字符串将由此脚本处理。

到目前为止一切顺利。

为了提高性能并保持页面响应,我想以多线程方式构建此字符串。由于这还不是Web标准,我在setInterval的帮助下进行了模拟。

现在我知道以这种方式做事的本质并不是等待结果。

但我想不出一种保持响应和快速响应并将完整结果返回给处理程序的方法。

因此最终结果(在此示例中)应显示:012345678910。

任何帮助/线索都将不胜感激。

干杯,另一个书呆子。

2 个答案:

答案 0 :(得分:1)

你需要反过来转向它。 Action不是回调,它不会使用异步结果,但生成它。另一方面,{em> 是回调,因为消耗结果(通过doTheMagic结果)。

因此,您应该将alert作为回调传递给Action,而不是将doTheMagic作为“回调”传递给doTheMagic

Action

function Run() { var handler = new CallBackStringHandler(); Action(function(result) { handler.doTheMagic(result); }); // or, alternatively: (only in modern browsers supporting Function.bind) Action(handler.doTheMagic.bind(handler)); }; 接受Action参数并在完成后调用它。最后,让callback收到doTheMagic。我分叉你的小提琴,have a look

注意:您不会使用result获得多线程,它仍会在与脚本其余部分相同的浏览器线程中运行。如果真正需要做一些严重的繁重工作,您可能需要use a web worker

对于大多数情况,例如像你一样连接一个字符串,这是过度的。工作人员生活在一个完全独立的环境中,您只能通过消息与他们进行通信,这会给您的应用程序带来相当大的复杂性。在确定您确实需要多线程方法之前,请确保进行大量测试和基准测试!

答案 1 :(得分:0)

所以为了得到最终答案,我有点解决这个问题(fork here):

function CallBackStringHandlerBy3rdParty() {};

CallBackStringHandlerBy3rdParty.prototype.doMagic = function(callback) {
    var result = callback.call(this);
    alert(result);
};

CallBackStringHandlerBy3rdParty.prototype.doMyOwnMagic = function(result) {
    if(result.isComplete) {
        this.doMagic(function(){return result.value;});
    } else {
        var that = this;
        result.value += 1;
        if(result.value < 10)
            setTimeout(function(){that.doMyOwnMagic(result);},10);      
        else {            
            result.isComplete = true;
            this.doMyOwnMagic(result);
        }
    }
};

function Run(){    
    var handler = new CallBackStringHandlerBy3rdParty();
    var result = {};
    result.value = 0;
    result.isComplete = false;
    handler.doMyOwnMagic(result);
};

Run();

干杯!