0

私たちのアプリケーションでは、堅牢なカウントダウン タイマーが必要です。タイマーがゼロになると、ユーザーを次のページに移動させます。

JavaScript でカウントダウン タイマーを作成することについて、ここには多くの質問があります。私はそれらの多くを整理し、多くのコード サンプルを調べ、多くのプラグインを試しましたが、この 1 つのテスト ケースではすべて失敗しました。 (時間を稼ぐ、時間を失う、または単にフリーズする)。その理由は、それらのほとんどが、最初の開始時刻を保存してから、(setTimeout または setInterval のいずれかを介して) 一定の間隔で現在の時刻を取得し、それと開始時刻の差分を取るというロジックに基づいているためです。システム時刻を調整すると、「現在の」時刻は、開始時刻の 1 時間または数日前、または数時間または数日後になる場合があります。

そこで、これらのシステム変更シナリオを処理するために、次のコードを考え出しました。私が行う主なことは、目盛り間隔を近似値として使用するために、開始時と現在の「差分」が負であるかどうか (または、自動夏時間調整を処理するために約 1 時間以上かどうか) を確認することです。また、開始時刻を各ティックの現在の時刻にリセットして、経過時間が最初の開始時刻と現在の時刻の差分だけでなく、差分間の時間の合計になるようにします。このアプローチに欠陥がある人はいますか?

var timeLeft = 60000, // time left in ms, 1 minute for this example
    startTime, 
    totalElapsedTime = 0,
    TICK_INTERVAL = 500; // the setTimeout interval


var timerTick = function () {

    var now = new Date(),
        elapsedTime = now.getTime() - startTime.getTime();

    // if the elapsed time was positive and less than approximately an hour, then add the elapsed time to the total
    // otherwise, add the TICK_INTERVAL, which we know is the theoretical minimum between timerTick() calls

    totalElapsedTime = (elapsedTime > 0 && elapsedTime < 3590000) ? totalElapsedTime + elapsedTime : totalElapsedTime + TICK_INTERVAL;

    // reset start time 
    startTime = now;

    // there is time left, so set up another tick
    if (totalElapsedTime < timeLeft) {

        // update the html that is displaying remaining time

        setTimeout(timerTick, TICK_INTERVAL);          

    }
    else {

        // time ran out, so do whatever you do when it runs out            

    }
}


// start the timer
startTime = new Date();
setTimeout(timerTick, TICK_INTERVAL);
4

1 に答える 1

1

次のことがうまくいかないのはなぜですか?

var timeleft = 60000,
    tick = 1000,
    intervalID = window.setInterval(function () {
        timeleft = timeleft - tick;
        if (timeleft <= 0) {
            // clear the interval
            clearInterval(intervalID);

            // do something
        }
    }, tick);

アップデート

使用setTimeout(これはドリフトしますが、アニメーションに使用しない限り、おそらく問題ありません):

var timeleft = 60000,
    tick = 1000;

window.setTimeout(function timerFn() {
    timeleft = timeleft - tick;
    if (timeleft > 0) {
        // set the next timeout
        setTimeout(timerFn, tick);
    } else {
        // do something
    }
}, tick);
于 2012-11-21T18:52:12.103 に答える