-2

'timestamp'属性を特定のHTML要素に設定するjspページがあります。これらの「タイムスタンプ」の値を使用して、経過時間を「10秒前に更新」(ツールチップとして)の形式で表示します。

問題のデモンストレーション用に静的HTMLページを作成しました。これは私のコードです:

<html>
    <head>
        <script type = "text/javascript">
            function setTime() {
                var currentDate = new Date();
                var elem = document.getElementsByClassName('supermaxvision_timestamp');
                if(elem) {
                    for (var i = 0; i < elem.length; i++) {
                        var timestamp = elem[i].getAttribute('timestamp');
                        if(timestamp) {
                            var startTimestamp = new Date();
                            startTimestamp.setTime(timestamp)
                            var difference = currentDate.getTime() -startTimestamp.getTime();
                            elem[i].innerHTML = difference + " milliseconds";
                        }
                    }
                }
                setInterval(setTime, 1000);
            }
        </script>
    </head>

    <body>
        <div class='supermaxvision_timestamp' timestamp='1353389123456' ></div>
        <div class='supermaxvision_timestamp' timestamp='1353389234567' ></div>
        <div class='supermaxvision_timestamp' timestamp='1353389345678' ></div>
        <div class='supermaxvision_timestamp' timestamp='1353389456789' ></div>
        <div class='supermaxvision_timestamp' timestamp='1353389567890' ></div>

        <button onclick="setTime()">start</button>
    </body>
</html>

このコードをコピーしてテキストファイルに貼り付け、ブラウザで開くことができます([スタート]ボタンを1回だけクリックします)。

問題は、最初はdivの値が1秒に1回更新されることです(コードとして- setInterval(setTime, 1000))。ただし、更新間隔はゆっくりと減少し、値は瞬時に更新されます。そして1分以内にブラウザは応答を停止します。

setIntervalループ内から呼び出しているのではありません。ここで何が間違っている可能性がありますか?

また、このコードはIEでは機能しません。

4

3 に答える 3

3

setInterval(fn, ms)今からこの間隔をクリアするまで、ミリ秒fnごとに実行すると言います。msただし、呼び出しごとに、最後の呼び出しと同じ新しい間隔を設定します。

したがって、繰り返しではなく、提供された関数を1回だけ呼び出すように変更setIntervalするだけです。新しいタイムアウトを再帰的に設定する関数を呼び出すことでエミュレートできます。間隔を空けてそれを行うと、止まることのない間隔がどんどん増えていきます。そして、それ自体を呼び出すたびに、スケジュールされた間隔の数は2倍になります。すぐに手に負えなくなります...setTimeoutsetTimeoutsetInterval

setIntervalまたは、関数の外に移動しsetTimeて1回だけ呼び出すこともできます。これにより、毎秒呼び出され続けます。言うように:

// button calls this.
function startTime() {
  setInterval(setTime);
}

function setTime() {
  // all that code, but minus the setInterval at the end
}
于 2012-11-20T06:15:25.850 に答える
0

setInterval再帰的に呼び出しています。新しい間隔が作成されるたびに、その間隔は新しい間隔を作成します。最終的に、ブラウザはそれを処理できなくなります。

多分あなたはむしろこのようなものを望みますか?

<button onclick="setInterval(setTime, 1000)">start</button>
于 2012-11-20T06:13:29.557 に答える
0

setIntervalは繰り返し関数を開始します-現在のように、setTimeはループを実行し、ロジックは毎秒setTimeoutを呼び出し、各setTimeout呼び出しは毎秒それ自体への別の繰り返し呼び出しを開始します。代わりにsetTimeoutを使用すると、1回だけ呼び出されますが、代わりに、関数宣言の外でsetIntervalを実行することをお勧めします。

<html>
    <head>
        <script type = "text/javascript">
            function GEBCN(cn){
                if(document.getElementsByClassName) // Returns NodeList here
                    return document.getElementsByClassName(cn);

                cn = cn.replace(/ *$/, '');

                if(document.querySelectorAll) // Returns NodeList here
                    return document.querySelectorAll((' ' + cn).replace(/ +/g, '.'));

                cn = cn.replace(/^ */, '');

                var classes = cn.split(/ +/), clength = classes.length;
                var els = document.getElementsByTagName('*'), elength = els.length;
                var results = [];
                var i, j, match;

                for(i = 0; i < elength; i++){
                    match = true;
                    for(j = clength; j--;)
                        if(!RegExp(' ' + classes[j] + ' ').test(' ' + els[i].className + ' '))
                            match = false;
                    if(match)
                        results.push(els[i]);
                }

                // Returns Array here
                return results;
            }
            function setTime() {
                var currentDate = new Date();
                var elem = GEBCN('supermaxvision_timestamp');
                if(elem) {
                    for (var i = 0; i < elem.length; i++) {
                        var timestamp = elem[i].getAttribute('timestamp');
                        if(timestamp) {
                            var startTimestamp = new Date();
                            startTimestamp.setTime(timestamp)
                            var difference = currentDate.getTime() -startTimestamp.getTime();
                            elem[i].innerHTML = difference + " milliseconds";
                        }
                    }
                }
            }
        </script>
    </head>

    <body>
        <div class='supermaxvision_timestamp' timestamp='1353389123456' ></div>
        <div class='supermaxvision_timestamp' timestamp='1353389234567' ></div>
        <div class='supermaxvision_timestamp' timestamp='1353389345678' ></div>
        <div class='supermaxvision_timestamp' timestamp='1353389456789' ></div>
        <div class='supermaxvision_timestamp' timestamp='1353389567890' ></div>
        <button onclick="setInterval(setTime, 1000)">start</button>
    </body>
</html>

また、これがIEで機能しない理由は、ドキュメントのgetElementsByClassNameメソッドを適切にサポートしていないためです。私はここでそれを見つけました:IE 8:オブジェクトはプロパティまたはメソッド'getElementsByClassName'をサポートしておらず、Rob Wもそこで良い説明をしていますが、簡単な答えのために、querySelectorAllを使用してIEで動作するように上記のコードを変更しました

OK、意味がないと言っただけですが、とにかくここにすべてのコードをコピーしました。上記は、実際にテストされた(ieとffでの)例です。

于 2012-11-20T06:17:02.383 に答える