7

Firefox 12で奇妙な問題が発生しました。setTimeout()が常に適切な長さを待機しているとは限りません。それとも、ジャイブしないのは日付のミリ秒ですか?

このフィドルをチェックしてください。基本的に、100msのsetTimeoutは、80msから110msの間のどこでも実行されるようです。ジョン・レシグのタイマーの説明に基づいて、私はもっと理解することができます。しかし、少ないですか?

最初の実行で正しく機能することがあるため、問題を確認するには、1〜2回更新する必要がある場合があります。IEとChromeではうまく機能しているようです。

フィドルで使用しているコードは次のとおりです。

var txt = '',
    TIMEOUT_LENGTH = 100,
    _now;

now = Date.now || function() { return new Date().getTime() };

function log(time) {
    c = time < 100? 'class="error"' : '';
    $('#log').append('<p '+c+'>waited ' + time + '</p>');
}

function defer() {
    var d = $.Deferred(),
        start = now();
    setTimeout(function() {
        d.resolve(now() - start);
    }, TIMEOUT_LENGTH);
    return d.promise();
}

for (var i = 0; i < 20; i++) {
    defer().then(log);
}

風変わりな出力のサンプルを次に示します。

ここに画像の説明を入力してください

これが私のブラウザ情報です:

ここに画像の説明を入力してください

そして、私の質問を読んでくれてありがとう!誰かがこれに光を当てることができることを願っています。

より詳しい情報

setInterval()を使用し、各増分をチェックして必要な時間が経過したかどうかを確認することで、問題を回避しました。このフィドルを参照してください

しかし、誰かが問題の原因に光を当てることができるかどうかを聞くことにまだ非常に興味があります

4

3 に答える 3

3

はい。setTimeoutの精度は多くの要因に基づいており、指定した正確な時間に常に実行されるとは限りません。

私はこれを何の権威もなしに言うことはできませんが、Firefox はより高速に見えるように、一時的に JS エンジンを高速化してすべてを動かそうとしているのではないかと思います (これは興味深いです。私の経験では、タイマーベースの私のバージョンのFirefoxでは、最初は関数の実行速度が実際に遅くなります)。

あなたが投稿したリンクが述べたように、正確なタイミングで実行されることsetTimeoutも約束もしていません。setIntervalただし、を使用するとsetInterval、遅れが大きすぎる場合に追いつくことで「自分自身を修正」できることを行うタイマーループの利点が得られるため、何をしようとしても、より適切な場合があります。

とにかく、これが私の Macbook 10.6.8 での結果です。

Firefox 5.0.1:

waited 92
waited 92
waited 93
waited 93
waited 93
waited 93
waited 93
waited 94
waited 93
waited 93
waited 93
waited 93
waited 94
waited 94
waited 94
waited 94
waited 94
waited 95
waited 96
waited 96

サファリ 5.1.5:

waited 100
waited 104
waited 104
waited 103
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104

クローム 19.0.1084.52:

waited 101
waited 103
waited 103
waited 104
waited 104
waited 103
waited 103
waited 103
waited 103
waited 103
waited 103
waited 103
waited 103
waited 103
waited 104
waited 104
waited 104
waited 104
waited 104
waited 104
于 2012-06-04T01:38:22.517 に答える
1

JavaScriptは同期的です。ブラウザはあなたsetTimeoutのをキューに追加し、後にそれらを実行します

  1. カウントダウンは終わりました
  2. カウントダウンが終了した時点でキューにある他のタスクはすべて終了しています。
于 2012-06-04T16:34:58.677 に答える
1

少なくとも指定されたミリ秒後にコードが実行されるように、次の関数を作成しました。setTimeout の代わりに使用します

mySetTimeout=function(f,t){
    var endTime=new Date().valueOf()+t;
    setTimeout(function(){
        var now=new Date().valueOf();
        if(now<endTime){
            mySetTimeout(f,endTime-now);
        }else{
            f();
        }
    },t);
};
于 2013-05-25T19:36:11.673 に答える