在没有setTimeout的情况下模拟JavaScript中的文本输入效果

时间:2014-04-21 00:48:30

标签: javascript jquery recursion

我正在制作一个RPG,并希望对话框显示一个打字效果(在对话框中输入一个字母)。我在setTimeout()遇到了一个递归问题,我在这里问:

How to ensure a recursive function isn't called again before it returns

SO用户推荐"避免在setTimeout中使用字符串......应该在数年和数年前停止教授;性能杀手,如果你在用户创建的字符串中进行混搭,就很容易造成非严格的eval-context错误。"

因此,如果我不应该使用setTimeout(),那么我怎样才能为屏幕上键入的字符串的每个字符添加延迟?

我能想到的一种方法是将变量计数器设置为x,并递减它(让我们说,设置i = 1000,然后循环直到i = 0,然后再次重复...直到字符串完全输入)但这会更快吗?它会解决问题吗?它也没有让我很好地了解减少需要多长时间。在setTimeout()中,您可以指定毫秒。

到目前为止,这就是我设计typeEffect的方式(它输入正常,但我可以继续点击继续重新运行脚本的类型按钮)。

typeEffect : function (index) {
    $("#responseButton").prop('disabled', true); //wait until typing is done before user can press again
    game.data.enableCycle = false;

    setTimeout(function () {
        $("#npc_dialog").append(game.data.NPCdialog.charAt(index));
        index++;
        if (index < game.data.NPCdialog.length) {
            Utilities.typeEffect(index);
        }
        else {
            game.data.enableCycle = true;
            Utilities.hoverText(); //after type effect, replace appended letters with full dialog, run hoverText to split it into spans (for hover text)
            $("#responseButton").prop('disabled', false);
            $('#npc_dialog').html(game.data.NPCdialog);
        }
    }, 50);     
},

2 个答案:

答案 0 :(得分:2)

使用setTimeout。您不应该在setTimeout中使用字符串

为:

setTimeout('foo(32)', 1000);

好:

setTimeout(function() {
  foo(32);
}, 1000);

我可以看到的问题是,每次按下按钮时都会启动一个新的并行setTimeout循环,而不会取消之前的循环。这是常见的模式:

var fooTimer = 0;
$(element).click(function(evt) {
  // clear the previous timer, if any
  if (fooTimer) {
    clearInterval(fooTimer);
  }
  // start a new timer
  fooTimer = setInterval(function() {
    foo(32);
  }, 1000);
}

需要注意的另一点是:setInterval / setTimeout是唯一可行的方法。你不能使用循环作为延迟,因为这样你的函数永远不会放弃线程。由于JavaScript是单线程的,并且与UI重绘共享一个线程,因此您的屏幕永远不会更新。你需要等待运行沙漏旋转所有字母的所有循环,并且几乎任何东西都阻止你的浏览器,然后你会看到一切都出现了。也就是说,除非浏览器认为您的代码没有出错并询问您是否要终止坏脚本。

答案 1 :(得分:0)

您可以使用setTimeout()或setInterval();做这样的事情会是首选的(唯一的?)方式。

我认为另一个SO用户指的是在字符串中设置回调代码而不是使用函数引用的做法,这已经有一段时间了。