【问题标题】:How to execute something only once within if-loop?如何在 if 循环中只执行一次?
【发布时间】:2015-05-03 00:21:28
【问题描述】:

编辑(更具体):

我有以下情况。我正在用 JavaScript 构建一个实验性的合成器接口。我正在使用howler.js 插件来处理音频。 这个想法是,如果满足特定条件,就会播放声音。我有一个数字存储变量,其值通过 iPhone 指南针的标题 改变。 我使用compass.js。它有一个名为标题的变量。

$(function(){

    Compass.watch(function (heading) {
      $('.degrees').text(Math.floor(heading) + '°');
      $('#rotate').css('-webkit-transform', 'rotate(' + (-heading) + 'deg)');

       if (heading >= 10 && heading <= 30) {
       sound.play("myFirstSound"); 
       } 
       else if (heading >= 31 && heading <= 60) {
       sound.play("mySecondSound");
       } else { etc etc...
       });
});

即使标题不变,.play 命令也不会执行一次,而是一遍又一遍地执行,导致音频引擎内存不足。如何仅在 if 循环中执行一次命令?我无法访问指南针功能之外的航向值。我总是得到 var 标题不存在 错误。

【问题讨论】:

  • 我在你的代码中没有看到循环......我必须想象它?
  • 添加计数器/触发变量...
  • IF 不是一个循环,而是条件如果那是你想说的。
  • 对不起。我还不熟悉循环的确切含义。原谅我粗鲁的表情。我认为这可能是一个循环,因为 if 中的命令被一遍又一遍地执行。那么它不符合循环条件吗?
  • 如果您不知道循环,您似乎正在编程超出您应该做的事情......而且我认为您的 ifs 处于某种循环中,以便触发超过一次。也许在一个经常被触发的函数中。

标签: javascript jquery html if-statement web


【解决方案1】:

取一个布尔变量,如

var checkOnce= false;
if (myVariable >= 10 && myVariable <= 30) {
checkOnce=true;
    sound.play("myFirstSound"); 
    } 
    else if (myVariable >= 31 && myVariable <= 60) {
checkOnce=true;
    sound.play("mySecondSound");
    } else { etc etc...

在循环中检查 checkOnce 的值。循环将一直运行到 checkOnce=false

【讨论】:

  • OP 希望有一个连续循环,然后在myVariable 值更改时播放不同的声音......这只是循环一次......
【解决方案2】:

创建一个boolean flag,只在false时播放声音。

var isPlayed = false;
var oldValue = myVariable;

if (myVariable >= 10 && myVariable <= 30 && !isPlayed) {
    sound.play("myFirstSound"); 
    isPlayed = false;
} 

然后在需要时初始化变量...对于您所说的,我想您将需要一个变量来比较循环内的值并将isPlayed标志设置为false

if (myVariable != oldValue)
    isPlayed = false;

【讨论】:

  • 我想补充一点,他必须为您的解决方案的每个条件添加一个标志。仅当 OP 想要在单个循环中播放除标记音频之外的其他音频时。问题不太清楚。
  • OP 想在每次变量更改值时播放声音,但只播放一次以避免内存问题...只需要一个标志...
  • 澄清。这个想法是每个条件只播放一个声音。 howler.js 旨在提供尽可能多的节点。这就是为什么我可以播放相同声音的多个实例。
【解决方案3】:

只需使用布尔变量。

var alreadyPlayed = false;

for(somecondition){
   if(alreadyPlayed) continue;

   sound.play("myFirstSound");
   alreadyPlayed = true;
}

你明白了。

【讨论】:

    【解决方案4】:

    布尔值是个好主意。您还可以使用sound 对象的onend 属性,这样您就会知道何时可以再次开始播放声音。像这样:

    var playing = false;
    sound.onend = function () { playing = false;  };
    
    while (condition) {
       if (!playing & ...)
           ...
       ...
    }
    

    【讨论】:

      【解决方案5】:

      看到您对问题的编辑,为下一个触发器添加延迟,指南针可能触发得太快了。不熟悉 compass.js 但正如我所见,它每度触发一次,这很多......如果你将手机倾斜 180 度,那就是 180 个触发器。 类似的,

      setTimeout(function() { your_func(); }, 50); 
      

      延迟 50 毫秒

      您还可以通过添加 10 个计数器将可用触发器限制在 360 到 36 个或更少,1 度表示 1 个计数。所以它只有在移动 10 度后才会触发。

      $(function(){
      var counter = 0;
      Compass.watch(function (heading) {
         if(counter <=10){
           counter++;
          }
          else{ 
         counter = 0;
        $('.degrees').text(Math.floor(heading) + '°');
        $('#rotate').css('-webkit-transform', 'rotate(' + (-heading) + 'deg)');
      
         if (heading >= 10 && heading <= 30) {
         sound.play("myFirstSound"); 
         } 
         else if (heading >= 31 && heading <= 60) {
         sound.play("mySecondSound");
         } else { etc etc...
         }       
         });
      });
      

      【讨论】:

      • 我试过了。现在发生了很多奇怪的事情。指南针的每个功能都会超时 10 步。如果我在指南针功能之外调整我的 if 逻辑怎么办?伤了那个工作?这就引出了另一个问题,即如何在罗盘函数之外读出航向变量?非常感谢您的关注。
      • 什么奇怪的东西?我认为您不会真正实现任何目标。从您的代码来看,您似乎每 30 度播放一次声音。尝试将您的计数器设为 30。抱歉,我不知道 compass.js 的行为,也不知道手机中的指南针。它会触发度数变化吗?
      • 标题变量在哪里声明?为了快速测试,添加一个 console.log(header);就在指南针手表功能之后。尝试阅读闭包以了解嵌套函数中的变量范围。
      • 谢谢 JaredT。标题变量似乎是插件的一部分。它没有在我的代码中声明。我想它是在 compass.js 中声明的。该插件似乎一直在寻找变化。这可以解释这种行为。我想到了另一种解决方案。由于我将学位编号发送到 HTML 以显示它,因此我不妨添加一个事件侦听器来监视 HTML 元素的内容。它不会很优雅,但如果它有效,我会很满意。
      • 您将只是传递触发器。除非你限制触发器,否则它会迅速触发。发生了什么奇怪的事情?我看不出代码有什么问题,也许有一些修饰,比如如果方向改变,立即播放声音。您是否尝试过计数器并将其设置为 360/(您有多少声音)?
      【解决方案6】:

      只添加一小层抽象来跟踪当前正在播放的内容。

      var nameOfSoundPlaying = null;
      
      function play(soundName) {
         if (nameOfSoundPlaying == soundName) { 
            return; 
         } else {
           if (nameOfSoundPlaying != null) {
              // stop currently playing sound (if still playing)
              ...
           }  
           nameOfSoundPlaying = soundName;
           sound.play(soundName);
         }
      }
      

      然后它会简化你的代码:

      $(function(){
      
          Compass.watch(function (heading) {
            $('.degrees').text(Math.floor(heading) + '°');
            $('#rotate').css('-webkit-transform', 'rotate(' + (-heading) + 'deg)');
      
             if (heading >= 10 && heading <= 30) {
                 play("myFirstSound"); 
             } 
             else if (heading >= 31 && heading <= 60) {
                 play("mySecondSound");
             } else { etc etc...
             });
      });
      

      【讨论】:

        猜你喜欢
        • 2022-01-03
        • 1970-01-01
        • 2019-12-03
        • 1970-01-01
        • 1970-01-01
        • 2023-04-02
        • 2020-07-17
        • 2015-01-18
        • 2013-08-12
        相关资源
        最近更新 更多