【问题标题】:Why does everything display at once, using setTimeout in Javascript?为什么使用 Javascript 中的 setTimeout 会立即显示所有内容?
【发布时间】:2013-09-05 22:26:25
【问题描述】:

我试图让一些东西在 javascript 中向下滚动屏幕,但是,在执行时,它只会说一点并立即显示所有内容。所以$("#Menu").html('') 函数并没有清除它,setTimeout(function {},500) 只是为整个页面而不是代码段设置超时。

var MenuData = [
{'Name':'pictures','x':'30'},
{'Name':'blog','x':'50'},
{'Name':'contact','x':'42'}
]
;  


var PositionArray = new Array();
$(document).ready(function () {
    for (var count = 0; count < 1000; count++) {
        $("#Menu").html('');
        if (PositionArray[count] != null) {
            PositionArray[count]++;
        } else {
            PositionArray[count] = 0;
        }

        setTimeout(function () {
        for (var i in MenuData) {
                $("#Menu").append('<div style="position:relative; left:' + MenuData[i].x + 'px; top:' + PositionArray[i] + 'px; ">123</div>');
            }
        }, 500);

    }
});

这是小提琴:http://jsfiddle.net/LbjUP/

编辑:代码中存在一些不适用于问题的错误。这是新的:http://jsfiddle.net/LbjUP/1/,我刚刚将 PositionArray[count] 作为 PositionArray[i] 移动到 setTimeout 函数中

【问题讨论】:

  • 因为你给它们的持续时间都是一样的。请注意,由于在 for 循环中使用 setTimeout 而没有正确创建保留 i 值的子范围,您还会遇到严重的范围问题
  • 基本上,您会立即同时创建 1000 个设置超时,所有这些都将在 500 毫秒后触发。因此,在 500 毫秒后,所有 1000 都会触发。
  • 我想你可以使用 500*count。您也可以设置它,以便 setTimeout 函数递归调用自身。
  • 有没有办法让 setTimeout() 每次都调用而不是等到 for 循环结束(这对我来说没有意义——为什么要这样做?)?
  • @Jamil:看我的回答。 setInterval 也应该可以工作,如果您在 1000 次通话后清除间隔计时器。实际上应该更好地避免调用堆栈。

标签: javascript jquery settimeout


【解决方案1】:

如 cmets 中所述,您将同时创建 1000 个超时 500 毫秒 - 500 毫秒后所有超时都将执行。您想要的是增加每个预定功能的超时时间:

setTimeout(function() {
    // do something
}, count * 500);

但是,一次创建 1000 次超时并不是一个好主意。最好使用setInterval 或“递归”调用setTimeout 直到计数达到1000,这样您一次只有一个活动超时。

var count = 0;
function update() {
    // do something
    if (++count < 1000)
        setTimeout(update, 500);
    // else everything is done
}
update();

另外,如果您打算在循环中创建超时,请确保为 familiar with closures 以及它们在循环运行后访问计数器变量时的行为。

【讨论】:

  • 递归设置setTimeout是我想做的。这将需要在每个 setTimeout 或执行相同操作的操作后暂停。我该怎么做?我的印象是 setTimeout 在程序上暂停了代码,显然它没有。
  • 没有。 setTimeout 确实异步将给定函数的执行安排在指定的时间,并立即返回。这不是sleep 函数,它会冻结整个浏览器 UI。
  • 好的。我尝试了第一种方法,它做了几乎相同的事情,虽然它似乎延迟或更多:jsfiddle.net/LbjUP/2我已经完成了类似于第二种的功能,所以它应该可以工作,我要试试出来。
【解决方案2】:

试试

function recurse ( cnt ) {
    for (var i in MenuData) {
        $("#Menu").append('<div style="position:relative; left:' + MenuData[i].x + 'px; top:' + PositionArray[i] + 'px; ">123</div>');
    }
    if (cnt < 1000){
       setTimeout(function () { recurse(cnt + 1); }, 500);
    }
}

$("#Menu").html('');
if (PositionArray[count] != null) {
    PositionArray[count]++;
} else {
    PositionArray[count] = 0;
}
recurse(0);

【讨论】:

    猜你喜欢
    • 2017-02-20
    • 2014-11-11
    • 2011-10-31
    相关资源
    最近更新 更多