-2

我有一个 jsp 页面,它为某些 HTML 元素设置了“时间戳”属性。我使用这些“时间戳”的值以格式显示经过的时间 - “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>

您只需将此代码复制粘贴到文本文件中并在浏览器中打开它(仅单击“开始”按钮一次)。

问题是最初我的 div 的值将每秒更新一次(作为代码 - setInterval(setTime, 1000))。但慢慢地,更新间隔会减少,值会立即更新。在一分钟内浏览器停止响应。

我不是setInterval从循环内调用。这里可能有什么问题?

此外,此代码在 IE 中不起作用。

4

3 回答 3

3

setInterval(fn, ms)fnms毫秒运行一次,从现在开始直到我清除这个间隔。但是在每次调用时,您都会设置一个新的间隔,与上一个相同。

所以简单改成setInterval哪个setTimeout不重复,只调用提供的函数一次。可以通过调用递归设置新超时的函数setTimeout来模拟。setInterval如果你用间隔来做这件事,你会安排越来越多的间隔,而且永远不会停止。每次它调用自己时,预定间隔的数量都会翻倍。很快就失控了……

或者,您可以将函数setInterval移出setTime并只调用一次,这将保持每秒调用一次。比如说:

// 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 开始一个重复函数 - 就像现在 setTime 一样,它是循环和逻辑,然后每秒调用 setTimeout,每个 setTimeout 调用然后每秒开始对自身进行另一个重复调用。如果您改用 setTimeout,它只会被调用一次,但我的建议是您只需在函数声明之外运行 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: Object doesn't support property or method 'getElementsByClassName'并且 Rob W 在那里也给出了很好的解释,但为了快速回答,我修改了上面的代码以在 IE 中工作,使用 querySelectorAll

  • Derp,这是一个 jQuery 方法 Chris,你为什么只假设人们使用 jQuery。getElementsByClassName & IE8:对象不支持此属性或方法包括来自 ascii-lime 的答案,它实现了它自己的 getElementsByClassName 版本。将所有代码复制到这里对我没有任何好处,但是如果您不想使用 jQuery,请去看看。

好的,我只是说没有意义,但无论如何我已经在这里复制了所有代码,上面是一个工作的、经过测试的(在 ie 和 ff 上)你想要的例子

于 2012-11-20T06:17:02.383 回答
0

您正在setInterval递归调用。每次创建新间隔时,该间隔都会创建一个新间隔。最终浏览器无法处理它。

也许你更喜欢这样的东西?

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