簡體   English   中英

如何在for ...循環中使用setTimeout

[英]How to Use setTimeout in a for…loop

我想要的是(新聞自動收錄機類型功能):

  1. 從ul標簽獲取li的列表
  2. 遍歷所有li並獲取文本
  3. 通過firefox console.log()在控制台中顯示文本
  4. 得到下一個李,重復直到顯示所有李

那是目標,但是setTimeout並沒有按照我的預期運行。 僅顯示LAST迭代(“后四”)。 那個(“第四后”)連續顯示四次。

<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>

發生這種情況的原因是由於關閉。 for循環塊周圍有閉包,因此當您引用“ li_text”時,它始終等於li_text設置為的最后一個值。 for循環不會為循環的每次迭代創建單獨的閉包。

正如Greg所提到的,問題在於閉包僅評估一次。 沒有人為此發布解決方案,所以這里是一個。 這使用添加每次生成回調函數的函數:

加:

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);
}

更改此:

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);
})()

我們如何稍微移動一些代碼呢...取出關閉問題...

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,或者您需要使用新的延遲專門增加每個函數的調用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM