間隔は、自分自身を再スケジュールするタイムアウトのようなものです (新しいタイムアウトを開始するタイムアウトとは異なります)。間隔はそれ自体が再スケジュールされるため、作成するのは 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) });
演習:
- カウントダウンが「完了」したときのコールバック関数を追加して、カウントダウンを連続して実行できるようにします。
- シリーズジェネレーターを消費し、それを使用して次の
count
値を生成します。
- カウントダウン
makeCountdown
の制御に使用できるオブジェクトを返します。
- 楽しむ!