如何无限重复 javascript setInterval 定时器两次

How to repeat javascript setInterval timer infinitely with two times

我正在开发一个计时器,它运行一定的分钟数,然后重新开始一段休息时间,倒计时然后回到原来的分钟数。我正在为逻辑而苦苦挣扎。到目前为止,我已经 运行 降低了原始时间,然后 运行 降低了中断计时器,但我需要帮助使其 return 达到原始时间并无限循环(或直到停止按钮被按下)。这是我拥有的:

    function timer(minutes, breakLength) {

    --minutes;

    timerId = setInterval(function() {

        if (minutes >= 0) {

            if (seconds > 0) {
                --seconds;
            }

            if (seconds == 0 && minutes == 0) {
                playSound();
                isBreak = true;
                minutes = breakLength;
                $('.type').html('Break');
                $('.timer').html(minutes + ':00');

            };

            if (seconds === 0) {
                seconds = 59;
                --minutes;
            }

            if (seconds < 10) {
                seconds = '0' + seconds;
            }

            $('.timer').html(minutes + ':' + seconds);
        }
    }, 1000);

}

我怎样才能让它重演?

在您的计时器函数范围内定义一个新变量作为超时 ID 持有者(我们称之为 resetTimeout):

var resetTimeout = null;

将此附加代码添加到主函数中

var runFor = 60000; // 60000ms or 1 minute

在主区间添加逻辑(第一行):

if(runFor <= 0) {
    if(!resetTimeout) {
       // Create a reset timeout
       resetTimeout = setTimeout(function(){ runFor = 60000; resetTimeout = null; }, breakLength);
    }
    return;
}
else {
    runFor -= 1000; // Deduct time of this interval
}

此逻辑从 runFor 中减去 1000 毫秒或 1 秒,直到它被完全消耗掉。然后创建一个 timeOut 函数,将其重置为原始值和 returns 当前函数,直到 runFor 被更新。我以 60000 毫秒为例,您可以在下面的完整代码中看到正确的版本。为什么我们将超时分配给变量?很简单,我们不想创建多个超时。我们将超时设置为 null 以允许在下一个时间间隔重新创建。

请注意,有更好的方法可以做到这一点,但我决定尽可能少地修改您的代码。

这是工作代码:

function timer(minutes, breakLength) {
    var seconds = 0;
    var originalMinutes = minutes;
    var resetTimeout = null;
    var totalRunFor = minutes * 60 * 1000; // Since minutes are independent
    var runFor = totalRunFor;

    timerId = setInterval(function() {
        if(runFor <= 0) {
            if(!resetTimeout) {
                
                // Create a reset timeout
                resetTimeout = setTimeout(function(){ runFor = totalRunFor; resetTimeout = null; }, breakLength);
            }
            return;
        }
        else {
            runFor -= 1000; // Deduct time of this interval
        }

        if (minutes >= 0) {

            if (seconds > 0) {
                --seconds;
            }

            if (seconds == 0 && minutes == 0) {
                //playSound();
                isBreak = true;
                minutes = originalMinutes;
                $('.type').html('Break');
                $('.timer').html(minutes + ':00');

            };

            if (seconds === 0) {
                seconds = 59;
                --minutes;
            }

            $('.timer').html(minutes + ':' + ((seconds < 10)?'0':'') + seconds);
        }
    }, 1000);

}
timer(1, 10000);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Run for a minute and stop for 10 seconds indefinitely.
<div class='type'></div>
<div class='timer'></div>

timer 函数

中将其分成多个函数在概念上可能更容易
function timer(minutes, breakLength) {
    var ci = null;

    function ACountdown(minutes, callback) {
        var mm = minutes,
            ss = 0;
        ci = setInterval(function () {
            --ss;
            if (ss < 0)
                ss += 60, --mm;
            if (mm < 0) {
                // done
                clearInterval(ci);
                setTimeout(callback, 0);
            } else {
                $('.timer').html(mm + ':' + seconds);
            }
        }, 1e3);
    }

    function A() {
        // returned from break
        $('.type').html = 'Countdown';
        ACountdown(minutes, B);
    }
    function B() {
        // just finished countdown
        playSound();
        // going on break
        $('.type').html = 'Break';
        ACountdown(breakLength, A);
    }

    // set up any click handlers here, e.g.
    document.getElementById('cancel_button').addEventListener('click', function c() {
        this.removeEventListener('click', c);
        clearInterval(ci);
    });

    // start invocation chain
    A();
}