【问题标题】:JavaScript - setInterval not executing inside do-while loop for each iterationJavaScript - setInterval 没有在每次迭代的 do-while 循环内执行
【发布时间】:2013-09-25 11:48:30
【问题描述】:

所以我试图用 Javascript 模拟那个基于记忆的旧游戏 Simon。

我目前正在尝试让“Simon”生成要“播放”的随机命令(点亮 div,并播放音频)。我编写了一个函数,该函数将命令列表/数组作为输入,Simon 使用setInterval 在每个命令播放之间以 1 秒的时间播放。

function go_simon(simon_array) {

    var counter = 0;
    var interval = setInterval( function() {

        var current_val = parseInt(simon_array[counter]);
        switch (current_val) {
            case 1:
                TL_lightOn();
                var interval_1 = setTimeout( function() { TL_lightOff() }, 600);
                break;
            case 2:
                BL_lightOn();
                var interval_2 = setTimeout( function() { BL_lightOff() }, 600);
                break;
            case 3:
                BR_lightOn();
                var interval_3 = setTimeout( function() { BR_lightOff() }, 600);
                break;
            case 4:
                TR_lightOn();
                var interval_4 = setTimeout( function() { TR_lightOff() }, 600);
                break;
        }
        counter++;
        if (counter >= simon_array.length) 
            clearInterval(interval);

    }, 1000);
}

我把这个函数放在一个do-while循环中,它作为主游戏循环,其中生成一个随机命令并将其附加到正在进行的命令列表中,并调用“go-simon”函数来播放返回当前的命令列表。

我原本打算让每个循环迭代包括:

 •Generate random command (1-4)
 •Append to running array of commands
 •Playback array of commands over time duration - # of commands * seconds

相反,循环...在不执行 go_simon 函数的情况下循环了多少秒。我将循环限制为 10 次迭代,每次迭代使用 alert()。这导致警报被快速连续调用 10 次,最后只调用一次 go_simon(),播放填充了 10 个命令的数组。

do {
    // create int 1-4 and append to global array
    generate_value();

    alert(simon_array);
    go_simon(simon_array);

    if (simon_array.length >= 10) {
            alert(simon_array);
        condition = false;
    }
} while (condition); 

关于如何让这个 do-while 循环让 go_simon 函数在每次迭代中正确执行有什么建议吗?

非常感谢

【问题讨论】:

    标签: javascript setinterval do-while


    【解决方案1】:

    你必须让go_simon 让你知道它什么时候完成,因为它是异步工​​作的。只有这样你才应该生成一个新值并再次调用它(可能在一定延迟之后)。

    你可以通过让函数接受一个回调来做到这一点,当你清除间隔时调用它:

    function go_simon(simon_array, callback) {
    
        var counter = 0;
        var interval = setInterval( function() {
    
            var current_val = parseInt(simon_array[counter]);
            switch (current_val) {
                case 1:
                    TL_lightOn();
                    var interval_1 = setTimeout( function() { TL_lightOff() }, 600);
                    break;
                case 2:
                    BL_lightOn();
                    var interval_2 = setTimeout( function() { BL_lightOff() }, 600);
                    break;
                case 3:
                    BR_lightOn();
                    var interval_3 = setTimeout( function() { BR_lightOff() }, 600);
                    break;
                case 4:
                    TR_lightOn();
                    var interval_4 = setTimeout( function() { TR_lightOff() }, 600);
                    break;
            }
            counter++;
            if (counter >= simon_array.length) {
                clearInterval(interval);
                callback();
            ;
    
        }, 1000);
    }
    

    不要使用同步循环,让函数从回调中再次调用,直到满足条件:

    function run(){
        generate_value();
        if (simon_array.length < 10) {
            go_simon(simon_array, run);
        }
    }
    run();
    

    【讨论】: