[英]Javascript setTimeout not working in a for-loop
我必須每秒更改圖像的來源。 我有一個for循環,其中調用一個具有超時的函數。 我在這里讀取了stackOverflow,但它不起作用。 可以請有人告訴我,我可以修復什么使其工作? 我一直在努力解決這個問題,我想承認。 謝謝。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript">
function changeImage(k) {
setTimeout(function(){
document.getElementById("img").src = k + ".png"; alert(k );}, 1000);
}
function test() {
for (var k = 1; k <= 3; k++) {
changeImage(k);
}
}
</script>
</head>
<body>
<div id="main_img">
<img id="img" src="http://placehold.it/110x110">
</div>
<input type="button" style="width: 200px" onclick="test()" />
</body>
在您的代碼中,您可以立即設置所有超時。 所以,如果你將它們都是一個二現在他們都火一家其次從現在。
您已經在索引k
傳遞,因此只需將時間參數乘以k
。
setTimeout(function(){
document.getElementById("img").src = k + ".png";
alert(k);
}, k * 1000);
// ^ added
問題是您正在創建一個相隔毫秒的計時器實例。 一秒鍾后,它們也會分開幾毫秒。 你需要的是以彼此相隔的設定間隔執行它們。
您可以使用setInterval
使用計時器,該計時器以給定的間隔執行提供的函數。 不要忘記殺掉計時器,否則它會永遠運行。
您可以將元素緩存在變量中,這樣您就不會經常訪問DOM。
另外,我會避開alert()
。 如果要調試,請在調試器中使用斷點。 如果你真的希望它是“類似警報”,那么使用console.log
並觀察控制台。
setInterval
優於遞歸setTimeout
一個優點是,您不會在每次迭代時生成多個計時器,而只會生成一個計時器。
這是建議的解決方案:
var k = 0;
var image = document.getElementById("img");
var interval = setInterval(function() {
// Increment or clear when finished. Otherwise, you'll leave the timer running.
if(k++ < 3) clearInterval(interval);
image.src = k + ".png";
// Execute block every 1000ms (1 second)
},1000);
而不是使用循環,你可以這樣做:
var k = 0;
var int = setInterval(function() {
if (k <= 3) k++;
else { clearInterval(int); }
document.getElementById("img").src = k + ".png";
alert(k);
}, 1000);
setTimeout不會停止程序執行,只會在1秒內為回調設置一個事件。 這意味着如果你在for循環中設置了三個setTimeout,它們將在1秒后同時執行。
您可以使用延遲遞歸,而不是使用for循環。
function changeImage(imageIndex) {
document.getElementById("img").src = imageIndex + ".png";
alert(imageIndex);
}
function myLoop( imageIndex ) {
if( imageIndex >= 3 ) return;
changeImage( imageIndex );
setTimeut( function() { myLoop(imageIndex + 1) }, 1000 );
}
setTimeut( function() { myLoop(0) }, 1000 );
var interval = null;
var imageIndex = 0;
function changeImage() {
document.getElementById("img").src = imageIndex + ".png";
alert(imageIndex);
imageIndex++;
if( imageIndex === 3 ) clearInterval( interval );
}
interval = setInterval( changeImage , 1000);
function changeImage(imageIndex) {
document.getElementById("img").src = imageIndex + ".png";
alert(imageIndex);
}
for( var i=0; i < 3; i++) {
setTimeout( changeImage.bind(window, i), i * 1000 );
}
(function f(i) { setTimeout( changeImage(i) || f.bind(window, i = (i++)%3), 1000); })(0)
我的建議是使用console.log()或alert()來幫助你調試 - 這將使得它變得更加明顯正在發生的事情。 例如,如果你在test或setTimeout函數中放置了console.log,你會發現所有三個圖像都是同時添加的。
我建議的是聲明你的“nextImage”函數,然后在該函數中定義你的setTimeout。 這樣它每秒都會自稱。
另一個提示:我假設您希望這三個圖像永遠循環,所以我添加了一個常用的技巧與模數運算符(%)來完成此任務。
看一看:
工作演示: http : //jsfiddle.net/franksvalli/PL63J/2/
(function(){
var numImages = 3, // total count of images
curImage = 1, // start with image 1
$image = document.getElementById("img"),
imageBase = "http://placehold.it/110x11";
function nextImage() {
$image.src = imageBase + curImage;
// increment by one, but loop back to 1 if the count exceeds numImages
curImage = (curImage % numImages) + 1;
// execute nextImage again in roughly 1 second
window.setTimeout(nextImage, 1000);
}
// initializer. Hook this into a click event if you need to
nextImage();
})();
正如其他人所說,你可能想要使用setInterval,你可以通過一些調整來做:
(function(){
var numImages = 3, // total count of images
curImage = 1, // start with image 1
$image = document.getElementById("img"),
imageBase = "http://placehold.it/110x11";
function nextImage() {
$image.src = imageBase + curImage;
// increment by one, but loop back to 1 if the count exceeds numImages
curImage = (curImage % numImages) + 1;
}
// initializer. Hook this into a click event if you need to
nextImage(); // call function immediately without delay
window.setInterval(nextImage, 1000);
})();
為什么它不起作用?
因為Javascript總是通過引用傳遞變量。 當您的代碼在隊列中等待時,變量已經更改。
我的解決方案
創建一個數組並按照出現的順序推送您想要執行的任何代碼(直接放置變量的實際值),例如:
var launcher = [];
launcher.push('alert("First line of code with variable '+ x +'")');
launcher.push('alert("Second line of code with variable '+ y +'")');
launcher.push('alert("Third line of code with variable '+ z +'")');
使用setInterval而不是setTimeout來執行代碼(您甚至可以動態更改延遲時間),例如
var loop = launcher.length;
var i = 0;
var i1 = setInterval(function(){
eval(launcher[count]);
count++;
if(i >= loop) {
clearInterval(i1);
}
}, 20);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.