0

順次カウントダウン タイマーを実行しようとしていますが、次の項目に進む前にタイマーが終了するのを待つ方法がわかりません。

for(var i = 0; i < 5; i++)
{
    var count = 5;
    var counter = setInterval(timer, 1000);
}

function timer()
{
    count--;
    if (count <= 0)
    {
        $('.workout-timer').text(count + "secs");
        clearInterval(counter);
        return;
    }

    $('.workout-timer').text(count + "secs");
}

これは単に負になりますが、for ループがなければ、コードは 5 から 0 にカウントダウンします。だから私の質問は、どのようにしていくつかのカウントダウンを次々と取得するのですか? タイマーはそれについて行く正しい方法ではありませんか?

4

2 に答える 2

1

間隔は、自分自身を再スケジュールするタイムアウトのようなものです (新しいタイムアウトを開始するタイムアウトとは異なります)。間隔はそれ自体が再スケジュールされるため、作成するのは 1 つのみです。(または、本当に必要な数だけ。)

元の投稿の問題は、5 つの間隔を作成し (ループ内で作成されていたため)、最後に作成された間隔の間隔 ID (内counter) のみを保持していたことです! したがって、clearInterval最後の間隔のみが停止し、他の 4 つの間隔は実行され、実行され、実行され続けました..

コメント付きで、元の問題のないクリーンアップされたコードを次に示します。

var count = 5;
// only need ONE interval
var counter = setInterval(timer, 1000);
// so we do one count RIGHT NOW
timer();

function timer() {
  // display first, so we start at 5: 5, 4 .. 1
  console.log(count);
  count--;
  if (count < 0) {
    // to repeat the count, comment out the clearInterval
    // and do `count = 5;` or similar .. take it from here :D
    clearInterval(counter);
  }
}

カウントダウンごとに個別の「状態」を作成するには、プロパティで状態を維持する新しいカウントダウン オブジェクトを作成するか、クロージャを使用します。これはクロージャーを使用した例です。また、コールバック関数のサポートを追加して、そのような関数をより汎用的にする方法を示しました。

function makeCountdown(startCount, delay, fn) {
    fn = fn || function (i) {
       // default action, if fn not specified
       console.log(i);
    };
    // local variables
    var count = startCount;
    var counter = setInterval(timer, delay);
    timer();

    function timer() {
        // now count and counter refer to variables in the closure (keyword!)
        // which are different each time makeCountdown is called.
        fn(count);
        count--;
        if (count < 0) {
            clearInterval(counter);
        }
    }
}

makeCountdown(20, 500); // uses default function
makeCountdown(10, 1000, function (i) { console.log(10 - i) });
makeCountdown(5, 2000, function (i) { console.log("SLOW! " + i) });

演習:

  1. カウントダウンが「完了」したときのコールバック関数を追加して、カウントダウンを連続して実行できるようにします。
  2. シリーズジェネレーターを消費し、それを使用して次のcount値を生成します。
  3. カウントダウンmakeCountdownの制御に使用できるオブジェクトを返します。
  4. 楽しむ!
于 2013-05-14T05:53:58.177 に答える
1

次のようなことができます。

function startCountdown(count, delay, callback) {
    if (!count) {
        callback && callback();
        return;
    }

    //do something here
    console.log(count);

    setTimeout(function () {
        startCountdown(--count, delay, callback);
    }, delay);
}

startCountdown(5, 1000, function () {
    startCountdown(5, 1500);
});

ただし、ネストされたコールバックが多数ある場合、これは面倒になる可能性がありますが、その問題に対処するために使用できる多くのアプローチのうちの 1 つを次に示します。

var queue = [
        { count: 5, delay: 1000 },
        { count: 10, delay: 200 },
        { count: 5, delay: 5000 }
    ];

processNextCountdown();

function processNextCountdown() {
    var options = queue.shift();

    if (options) {
        startCountdown(options.count, options.delay, processNextCountdown);
    }
}
于 2013-05-14T05:47:30.627 に答える