等待递归jQuery函数完全完成

时间:2013-10-24 01:48:49

标签: javascript jquery recursion

另一个应该简单,但却给我带来麻烦。我试图了解jQuery的.Deferred()和.promise()功能,以延迟某些操作,直到递归函数完全完成。目前,我的代码类似于以下内容:

    function showText(setTarget, setMessage, setIndex, setInterval) {
        var defer = jQuery.Deferred();
        var doShowText = function (target, message, index, interval) {
            if (index < message.length) {
                $(target).append(message[index++]);
                setTimeout(function () { doShowText(target, message, index, interval); }, interval);
            }
            else {
                alert("Done!");
                defer.resolve();
            }
        };

        doShowText(setTarget, setMessage, setIndex, setInterval);
        return defer.promise();
    }

function startButtonClick() {
    displayElement($("#getElement"));
    showText($("#getElement > h1"), "This text will slowly write to the screen.", 0, 50).promise()
        .then(alert("Finished."));

}

当它运行时,“完成”警报(我试图推迟)在第一次执行递归脚本后运行,因此当只打印一个字母时(而不是预期的结果)它将出现。但是,一旦打印完所有字母并且递归完成后,“完成”警报就会正确显示,因此似乎我的延迟变量在此之前不应被解析。任何人都可以帮助我发现为什么在这里早期调用“完成”警报?任何帮助表示赞赏!

编辑:我意识到我不小心发布了稍微旧版本的代码。它已使用正确的版本进行更新(运行时的行为相同)。

3 个答案:

答案 0 :(得分:2)

startButtonClick函数中,您无需在.promise()的结果上调用showText,因为您已经在showText内执行此操作。接下来,then回调的参数应该是一个函数,现在你立即调用alert函数,而不是将它作为函数传递,这就是它立即显示的原因,所以只需将它包装在一个函数中:

function(){ alert("Finished."); }

这是一个包含代码的jsfiddle:http://jsfiddle.net/RnLXF/

答案 1 :(得分:2)

这种情况正在发生,因为您实际上是在执行alert函数而不是传递函数引用。

请改为:

.then(alert.bind(null, 'finished'));

或者

.then(function () {
    alert('finished');
});

答案 2 :(得分:1)

这里有一个小提琴,包裹着一个漂亮的小物件: http://jsfiddle.net/YVZKw/3/

正如 plalx ctcherry 已经说过,最大的问题是你的.then电话中缺少一个功能。

<强> HTML

<a href='javascript:void(0)'>Start</a>

<div id='sampleElement'>
    <h1></h1>
</div>

<强>的JavaScript

$('a').on('click', function(){

    new ShowText(
        $("#sampleElement > h1"), 
        "I will slowly write text to the screen.",
        50
    )
    .done(function(){
        alert("Finished.")
    });
});

function ShowText(target, message, speed)
{
    me = this;
    me.target = target;
    me.message = message;
    me.index = 0;
    me.speed = speed;
    me.defer = new $.Deferred();

    me.interval = setInterval(function() {
        me.target.append(me.message[me.index++]);
        if (me.index > me.message.length) {
            clearInterval(me.interval);
            me.defer.resolve();
        }
    }, me.speed);

    return me.defer;
}
相关问题