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

JavaScript Asynch Callback - How to await the endresult

本文关键字:等待 结果 回调 异步 何等待 JavaScript      更新时间:2023-09-26

我有以下情况(另见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.

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

干杯,又是一个书呆子。

你需要把它反过来。Action不是回调,它不消费异步结果,但它产生它。另一方面,doTheMagic 回调,因为它消耗结果(通过alert处理结果)。

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

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只接收result。我把你的小提琴叉开了,你看!

注意:你不会得到多线程使用setInterval,它仍然会运行在相同的浏览器线程作为你的脚本的其余部分。如果你真的需要做一些繁重的工作,你可能需要使用web worker。

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

对于最终答案,我是这样解决的(fork在这里):

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

干杯!