2011-11-09 44 views
1

我想是这样的(新闻股票型功能):如何使用的setTimeout在为...循环

  1. 从UL标签
  2. 环获得李的名单通过所有李时珍和获取文本
  3. 显示在通过火狐的console.log()
  4. 获得下Li和重复,直到所有李时珍已经显示

这是我们的目标控制台文本,但setTimeout没有运行,因为我认为它会。只显示最后一次迭代(“后四次”)。那(“邮政四”)连续显示四次。

<body> 
<ul id="post_list"> 
<li>Post One</li> 
<li>Post Two</li> 
<li>Post Three</li> 
<li>Post Four</li> 
</ul> 

<script type="text/javascript"> 
var ul = document.getElementById('post_list'); 
var li = ul.getElementsByTagName('li'); 

for(var x=0; x < li.length; x++){ 
    var li_text = li[x].childNodes[0].nodeValue; 
    setTimeout(function(){showText(li_text)}, 1000); 
} 

function showText(text) { 
    console.log(text); 
}   
</script> 
</body> 
+3

经典功能 - 在 - 一个循环的问题。这个问题一遍又一遍地被询问...... –

+1

检查右列的“相关”列表(与输入问题标题时的列表基本相同,您看到了吗?)。 – BalusC

+0

可能的重复[JavaScript关闭如何工作?](http://stackoverflow.com/questions/111102/how-do-javascript-closures-work) –

回答

4

发生这种情况的原因是因为关闭。 for循环块已关闭,所以当您引用'li_text'时,它始终等于li_text设置为的最后一个值。 for循环不为通过循环为每次迭代创建一个单独的闭包。

+0

检查到它。 – sleeper

+1

嗯..好像我偶然发现了一个大黄蜂巢!在回顾了答案之后,这是对什么是错误**和为什么**的最好解释。我对获取代码修复不感兴趣,而是需要**理解**为什么我没有得到正确的结果。在这种情况下,似乎答案是*闭包*。所以我即将去尝试更清楚地理解这个问题。 – sleeper

+0

@Sleeper,如果你不希望超时是连续的,为什么你不创建一个超时,在超时后循环?不需要关闭和相同的功能。叹。 :) – Esailija

0

更改此:

for(var x=0; x < li.length; x++){ 
    var li_text = li[x].childNodes[0].nodeValue; 
    setTimeout(function(){showText(li_text)}, 1000); 
} 

要:

for(var x=0; x < li.length; x++) (function() { 
    var li_text = li[x].childNodes[0].nodeValue; 
    setTimeout(function(){showText(li_text)}, x * 1000); 
})() 
+2

这是一个非常复杂的答案,一个治疗症状而不是问题的真实案例。 – GAgnew

0

怎么样,我们只是将一些张望了一下代码...取出关闭问题...

var ul = document.getElementById('post_list'); 
var li = ul.getElementsByTagName('li'); 

for (var x = 0, xl = li.length; x < xl; x++) { 
    var li_text = li[x].innerText || li[x].textContent; // does IE support textContent?? 
    showText(li_text, x * 1000); 
} 

function showText(text, delay) { 
    setTimeout(function() { 
     console.log(text); 
    }, delay); 
} 

我假设你想要连续的延迟(因此循环)。因为setTimeout没有被阻塞,所以你需要在函数上有一个回调来调用下一个setTimeout,否则你需要用一个新的延迟专门增加每个函数调用。

+0

是你没有缓存长度。你意识到“李”是生命的权利?并且'.length'很贵 – Raynos

+0

我不打算解决所有与代码有关的问题......否则我只会用“YU NO USE DOM”来回答一半的jQuery问题 – rlemon

+0

没有理由复制粘贴错误码。你也可以使用'.childNodes'而不用过滤掉文本节点。 '.nodeValue'也不会做你认为它做的事。我想你想'.textContent' – Raynos

2

格雷格提到的问题是关闭只评估一次。没有人为此发布解决方案,所以这里是一个。这使用添加生成的回调函数,每次一个函数:

地址:

function getShowTextCallback(text) { 
    return function(){showText(text)} 
} 

然后用它在循环这样的:

for(var x=0; x < li.length; x++){ 
    var li_text = li[x].childNodes[0].nodeValue; 
    setTimeout(getShowTextCallback(li_text), 1000); 
}