jQuery:制作一个插件等到现有的调用完成后才能执行?

时间:2014-08-15 01:05:54

标签: javascript jquery plugins

我首先应该说,虽然我非常熟悉基本的JavaScript / jQuery,但我绝不是专家。所以这可能是一个我不能理解的简单概念。无论如何,我会尽我所能解释我的情况。

我一直在拼凑一个jQuery插件,它接受一个字符串并一次显示一个字符,直到到达字符串的结尾。每个呼叫根据需要在一段时间内开始和停止,直到完成:

$.fn.writeText = function(content) {
    var elem = this;
    var contentArray = content.split("");

    return this.each(function() {
        var current = 0;
        var length = contentArray.length;
    intervalText();     

    function intervalText(){
        var interval = setInterval(function(){
            if(current < length){   
            //If end punctuation is detected [omitted for simplicity's sake]
            {
            elem.text(elem.text() + contentArray[current++],play('tes.wav'));
            clearInterval(interval);
            setTimeout(function(){intervalText();},500);
            }
            //Else if 'pause' punctuation is detected.
            {
                elem.text(elem.text() + contentArray[current++],play('tes.wav'));
                clearInterval(interval);
                setTimeout(function (){intervalText();},200);
            }
            else{
                elem.text(elem.text() + contentArray[current++],play('tes.wav'));
                }
        }
        else if(current == length+1){
            clearInterval(interval);
        }
    }, 50);
    }
    });
}

我注意到的一件事是背靠背使用插件会导致问题:

$("#promptText").writeText("This test.");
$("#promptText").writeText("This is also a test.");
//Results in "TThhiiss tiess ta.lso a test."

我很快就确定问题只是字符被添加到同一个元素中,并且插件没有做任何事情&#34;错误。&#34;但是,正如您可以想象的那样,我希望防止这种情况发生。

为了做到这一点,我需要对插件进行任何二次调用,直到之前的插件完成为止。关于我如何处理此事的任何建议?

1 个答案:

答案 0 :(得分:0)

这是jQuery的Deferred()对象的一个​​很棒的应用程序。 Deferreds允许你启动一个函数,然后在该函数完成后链接其他调用($ .ajax()函数在内部使用Deferreds。)

在这种情况下,每次调用$()。writeText()时都可以排队一个新的Deferred,并让它们按顺序调用你的内部函数:

var deferred;
$.fn.writeText = function (content) {
    var d = $.Deferred(); //Each execution gets its own deferred
    var elem = this;
    var f = function () {
        writeTextInternal(content, elem, d); //Do it
    }
    if (deferred) { //If there is already a deferred, queue the new request
        deferred.then(f); //Calls f() when deferred is resolved, or immediately if already resolved
    } else {
        f(); //Call immediately, because there are no deferreds
    }
    deferred = d.promise(); //Save this deferred to chain subsequent calls.
    return deferred; //Allows other functions to do something after this text is typed.
}

var writeTextInternal = function(content, elem, d) {
    //Slightly modified original function that will resolve our deferred...
}

使用JSFiddle:http://jsfiddle.net/bt5tee3r/3/