【问题标题】:Can a for-loop wait until a function within it has finished executing?一个 for 循环可以等到其中的一个函数执行完毕吗?
【发布时间】:2015-11-05 18:14:38
【问题描述】:

我正在构建一个西蒙游戏,并为每个新回合构建了一个函数:

var game = [];
var squares = ["green", "red", "blue", "yellow"];

var newRound = function() {
  // adds a new round to the end of the game array
  game.push(squares[Math.floor(Math.random() * squares.length)]);

  // for loop to run through the game array
  for (var x = 0; x < game.length; x++) {
    playButton(game[x]);
  }
}

然后,我构建了另一个函数来控制每次方块被用户击中或循环通过我的 for 循环时的动画和声音

var playButton = function(color){
  $("#"+color).addClass(color+"--active active", 300, function(){
     $("#audio-"+color).trigger('play');
     $("#"+color).removeClass(color+"--active active", 300)
});

现在,我的 for 循环只是一次性遍历所有动画和声音。如何让 for 循环等待 playButton 函数完成执行,然后再循环执行?

code sample on CodePen

【问题讨论】:

  • $("#"+color).removeClass(color+"--active active", 300) 参数300 是什么意思?
  • @AndrewEvt 我猜它的延迟以毫秒为单位
  • @AndrewEvt "决定动画运行时间的字符串或数字。"
  • 我们看的是同一页吗,伙计们? api.jquery.com/addclass
  • @AndrewEvt,不。 api.jqueryui.com/removeclass

标签: javascript jquery function for-loop


【解决方案1】:

您可以将您的 for 循环转换为一个递归函数,该函数播放当前按钮,然后在所有动画完成后尝试播放下一个按钮。比如:

var newRound = function() {
  // adds a new round to the end of the game array
  game.push(squares[Math.floor(Math.random() * squares.length)]);

  // start playing from the first button
  playButton(game, 0);
}

function playButton(game, index) {
  if (index < game.length) { // if this button exists, play it
    var color = game[index];
    $("#" + color).addClass(color + "--active active", 300, function() {
      $("#audio-" + color).trigger('play');
      $("#" + color).removeClass(color + "--active active", 300, function() {
        playButton(game, index + 1); // once this button was played, try to play the next button
      });
    });
  }
}

【讨论】:

  • 这是一个很好的解决方案,谢谢。一个奇怪的错误发生了,但当一个按钮连续按下两次时,声音只播放第一次。我将毫秒数增加到 400 并且不再发生。知道为什么吗?
  • 没问题,很高兴为您提供帮助。至于您的问题,您需要决定如何处理允许用户在制作动画时点击它们。如果您想在动画进行时忽略他们的点击,一个简单的解决方法是添加一个标志,例如,isAnimating,它被初始化为false。然后,在您的click 处理程序中,如果此标志为false,则启动动画,然后将标志设置为true,并在动画完成后将其设置回false。这将确保用户无法通过大量点击来启动大量动画:)
【解决方案2】:

Javascript 是单线程的,因此您所要求的已经在发生。但是,您的 DOM 没有更新,因为有时您的 DOM 元素不存在。 DOM 更新与您的 javascript 不同步。

因此,您可以按设定的时间间隔执行 playButton 函数。

if(x<game.length) {
   setInterval(playButton(x), <someSmallNumber like 0.2 milliseconds>);

}

然后增加 x。通过增加颜色,x 也会增加,因为它是通过引用传递的。

var playButton = function(color){
     $("#"+color).addClass(color+"--active active", 300, function(){
     $("#audio-"+color).trigger('play');
     $("#"+color).removeClass(color+"--active active", 300)
     color++;
});

【讨论】:

  • 通过增加颜色,x 会增加这是不正确的。 JS 是 pass-by-value,所以 color 包含 x 值的副本,并且更新它不影响 x
猜你喜欢
  • 2021-02-15
  • 2015-03-04
  • 2019-08-15
  • 1970-01-01
  • 1970-01-01
  • 2019-07-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多