52

これは本当に簡単な質問です。を使用する場合setInterval(something, 1000)、たとえば31日後に、正確に「何か」がトリガーされることを完全に確信でき60*60*24*31ますか?または、いわゆるドリフトのリスクはありますか?

4

3 に答える 3

41

簡単な答え:いいえ、確信が持てません。はい、ドリフトする可能性があります。

長い答え:JavaScript時間の精度とJavaScriptタイマーのしくみについてのJohnResig 。

2番目の記事から:

タイマーが内部でどのように機能するかを理解するために、調査する必要のある重要な概念が1つあります。それは、タイマーの遅延が保証されていないということです。ブラウザのすべてのJavaScriptはシングルスレッドで実行されるため、非同期イベント(マウスクリックやタイマーなど)は、実行が開始されたときにのみ実行されます。

両方の記事(およびそのサイトのすべてのもの)は素晴らしい読み物ですので、それを読んでください。

于 2009-06-12T08:56:40.490 に答える
25

Firefoxで実行できるベンチマークは次のとおりです。

var start = +new Date();
var count = 0;
setInterval(function () {
    console.log((new Date() - start) % 1000,
    ++count,
    Math.round((new Date() - start)/1000))
}, 1000);

最初の値は、可能な限り0または1000に近づける必要があります(他の値は、トリガーのタイミングが「オフスポット」であったことを示します)。2番目の値は、コードがトリガーされた回数であり、3番目の値は回数です。トリガーされるべきでした。CPUを停止すると、その場からかなり外れる可能性がありますが、それ自体は修正されているようです。長時間実行して、どのように処理されるかを確認してください。

于 2009-06-12T09:04:41.267 に答える
2

(私の悪い英語について申し訳ありません)私は関数のカウントダウンについて同じ問題を抱えていました、私は関数countdown()とsetIntervalでループを書きましたが、ループごとに1〜3ミリ秒ドリフトします。それから私はドリフトがあるかどうかを制御する関数を書き、それを修正しました。

それは実際の分と秒だけで制御します。ここにあります。それは私にはうまく機能します、私はそれがあなたにも役立つことを願っています。

$.syncInterval(functionname,interval,controlinterval)

例:

countdown(){ some code };
$.syncInterval(countdown,1000,60);

1000ミリ秒ごとにカウントダウン機能を実行し、60秒ごとにチェックすると書かれています

コードは次のとおりです。

$.syncInterval = function (func,interval,control) { 
        var 
        now=new Date();
        realMinute=now.getMinutes(),
        realSecond=now.getSeconds(),
        nowSecond=realSecond,
        nowMinute=realMinute,
        minuteError=0,
        countingVar=1,
        totalDiff=0;

        var loopthat = setInterval(function(){

        if (nowSecond==0) {
            nowMinute++;
            nowMinute=nowMinute%60;
        };
        if (countingVar==0){

            now=new Date();
            realSecond=now.getSeconds();
            realMinute=now.getMinutes();

            totalDiff=((realMinute*60)+(realSecond))-((nowMinute*60)+(nowSecond));
            if(totalDiff>0){
                for (i=1;i<=totalDiff;i++) {
                    func();
                    nowSecond++;
                    countingVar++;
                };
            } else if (totalDiff==0){
                func();
                nowSecond++;
                countingVar++;
            } else if (totalDiff<0) {

            };
        } else {
            func();
            nowSecond++;
            countingVar++;
        };
        countingVar=countingVar%control;
        nowSecond=nowSecond%60;
    },interval);
};
于 2013-04-29T00:09:44.730 に答える