45

我想在另一个自定义函数完成后执行一个自定义jQuery函数
第一个函数用于创建“打字”效果

function Typer()
{
    var srcText = 'EXAMPLE ';
    var i = 0;
    var result = srcText[i];
    setInterval(function() {
        if(i == srcText.length) {
            clearInterval(this);
            return;
        };
        i++;
        result += srcText[i].replace("\n", "<br />");
        $("#message").html( result);
    },
    100);

}

第二个功能播放声音

function playBGM()
{
    document.getElementById('bgm').play();
}

我一个接一个地调用函数,比如

Typer();
playBGM();

但是随着文本的输入,声音开始播放。我只想在打字完成后播放声音。

这是我尝试过的:http: //jsfiddle.net/GkUEN/5/

我怎样才能解决这个问题?

4

4 回答 4

75

您可以使用以下代码

$.when( Typer() ).done(function() {
       playBGM();
});
于 2013-10-30T05:22:47.840 回答
37

您应该使用回调参数:

function Typer(callback)
{
    var srcText = 'EXAMPLE ';
    var i = 0;
    var result = srcText[i];
    var interval = setInterval(function() {
        if(i == srcText.length - 1) {
            clearInterval(interval);
            callback();
            return;
        }
        i++;
        result += srcText[i].replace("\n", "<br />");
        $("#message").html(result);
    },
    100);
    return true;


}

function playBGM () {
    alert("Play BGM function");
    $('#bgm').get(0).play();
}

Typer(function () {
    playBGM();
});

// or one-liner: Typer(playBGM);

因此,您将一个函数作为参数 ( callback) 传递,该函数将在if之前调用return

此外,是一篇关于回调的好文章。

function Typer(callback)
{
    var srcText = 'EXAMPLE ';
    var i = 0;
    var result = srcText[i];
    var interval = setInterval(function() {
        if(i == srcText.length - 1) {
            clearInterval(interval);
            callback();
            return;
        }
        i++;
        result += srcText[i].replace("\n", "<br />");
        $("#message").html(result);
    },
    100);
    return true;
        
    
}

function playBGM () {
    alert("Play BGM function");
    $('#bgm').get(0).play();
}

Typer(function () {
    playBGM();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
<div id="message">
</div>
<audio id="bgm" src="http://www.freesfx.co.uk/rx2/mp3s/9/10780_1381246351.mp3">
</audio>

JSFIDDLE

于 2013-10-30T05:20:26.773 回答
4

您还可以使用自定义事件:

function Typer() {
    // Some stuff

    $(anyDomElement).trigger("myCustomEvent");
}


$(anyDomElement).on("myCustomEvent", function() {
    // Some other stuff
});
于 2014-10-30T16:29:15.423 回答
3

Deferred Promise 是一种将函数执行整齐而轻松地链接在一起的好方法。无论是 AJAX 还是普通函数,它们都提供了比回调更大的灵活性,而且我发现更容易掌握。

function Typer()
{
var dfd = $.Deferred();
    var srcText = 'EXAMPLE ';
    var i = 0;
    var result = srcText[i];

更新 :

////////////////////////////////

  var timer=    setInterval(function() {
                    if(i == srcText.length) {

    // clearInterval(this);


       clearInterval(timer);

////////////////////////////////


   dfd.resolve();
                        };
                        i++;
                        result += srcText[i].replace("\n", "<br />");
                        $("#message").html( result);
                },
                100);
              return dfd.promise();
            }

我已经修改了 play 函数,所以当音频播放完毕时它会返回一个 promise,这可能对某些人有用。第三个函数在声音播放完毕时触发。

   function playBGM()
    {
      var playsound = $.Deferred();
      $('#bgm')[0].play();
      $("#bgm").on("ended", function() {
         playsound.resolve();
      });
        return playsound.promise();
    }


    function thirdFunction() {
        alert('third function');
    }

现在用以下代码调用整个事情:(一定要使用 Jquery 1.9.1 或更高版本,因为我发现 1.7.2 一次执行所有函数,而不是等待每个函数解决。)

Typer().then(playBGM).then(thirdFunction);  

在今天之前,我没有运气以这种方式使用 deferred promises,终于掌握了它。精确定时、链式接口事件在我们想要的时候发生,包括异步事件,从来都不是一件容易的事。至少对我来说,我现在可以控制它,这主要归功于其他人在这里提出问题。

于 2017-08-15T09:13:17.533 回答