3

我有一个数组s=[John; Alex; Mark],我想以 3 秒的延迟一个一个地显示这个数组的元素。

for (var i=0; i<=3; i++)
  {
     setTimeout(function(){x.innerHTML=s[i]},3000)
  }

这似乎很简单的问题,但我无法弄清楚。

4

8 回答 8

13
  1. 你的循环运行四次,而不是三
  2. setTimeout以小写字母开头s
  3. 你的延迟应该是 3000 3 秒,而不是 2000
  4. 你的延迟应该是3000 * i,不是,3000否则他们会同时开火
  5. 如果没有特别的预防措施,你不能在异步回调中使用循环变量 - 回调将看到最后分配给i的值,而不是你通过循环时的值。

这有效,并且完全避免了循环变量问题:

var s = ['John', 'Mark', 'Alex'];
var i = 0;

(function loop() {
    x.innerHTML = s[i];
    if (++i < s.length) {
        setTimeout(loop, 3000);  // call myself in 3 seconds time if required
    }
})();      // above function expression is called immediately to start it off

请注意它如何使用“伪递归”在上一次迭代完成后 3000 毫秒触发下一次迭代。这比让n所有未完成的计时器同时等待更可取。

http://jsfiddle.net/alnitak/mHQVz/

于 2013-04-03T13:23:14.910 回答
1

http://jsfiddle.net/rlemon/mHQVz/1/

我得修修补补……尽管这可能不是最好的解决方案,但它很有趣。

var x = document.getElementById('x'),
    s = ['John', 'Mark', 'Alex'];

(function loop() {
    s.length && (x.innerHTML = s.shift(), setTimeout(loop, 3000));
})();

Alnitak的解决方案要好得多。然而,它们都可以工作(他的可读性更高,而且不那么hacky,也不会破坏数组)。

于 2013-04-03T13:53:30.667 回答
1

这也将有所帮助:

const fruits = ['apple', 'banana', 'mango', 'guava'];
let index = 0;
const primtMe = (value, i) => {
    if (i < fruits.length) {
        setTimeout(() => {
            console.log(i + ' value = ' + value)
            primtMe(fruits[i + 1], i + 1)
        }, 3000);
    } else {
        return;
    }
}

primtMe(fruits[index], index)
于 2019-02-25T17:12:04.760 回答
0

您的代码将不起作用,因为您一次设置了 2000 毫秒(即2 秒)的四个超时。您最好使用设置三个超时(按数组中的元素数)的闭包,延迟为3000 毫秒。可以使用以下代码完成(注意是小写字母):setTimeout

var s = ["John", "Alex", "Mark"];
for (var i = 0; i < s.length; i++) {
    (function(i) {
        setTimeout(function() {
            x.innerHTML = s[i];
        }, 3000 * i);
    })(i);
}

演示:http: //jsfiddle.net/6Ne6z/

于 2013-04-03T13:22:47.033 回答
0

尝试

var s=['John', 'Alex', 'Mark'];
var x = document.getElementById('x');

function display(i){
    if(i >= s.length){
        i = 0;
    }

    x.innerHTML = s[i];
    setTimeout(function(){
       display(i + 1)
    }, 2000)
}

display(0)

演示:小提琴

于 2013-04-03T13:25:52.770 回答
0

如果你不使用闭包,你最终会得到 i 未定义。这是因为在每次迭代中,您都在覆盖 i 是什么。到它完成时,它将是未定义的。使用闭包将保留 i。

另一方面,当您可以检查长度时,硬编码值(即 i<3)是没有意义的。这样,如果 s 发生变化,您的 for 循环仍将获取所有内容。

var s = ['john','mark','brian'];
for (var i = 0; i < s.length; i++) {
    (function(i) {
        setTimeout(function() {
            x.innerHTML = s[i];
        }, 3000*(i+1));
    })(i);
}
于 2013-04-03T13:27:24.870 回答
0

您可以使用setInterval延迟 3 秒后一个一个地显示元素:

s=["John", "Alex", "Mark"];

var i = 0;
var id = setInterval(function(){                
            if(i > s.length) {                  
                clearInterval(id);                  
            }
            else{
                console.log(s[i++]);
            }
}, 3000);
于 2018-02-09T20:29:41.373 回答
0

在没有伪递归的情况下试试这个

var arr = [10,20,30,40]; // your array
var i = 0;
var interval = 2000 // 2 sec, you can add your time required
function callInterval() {
// set a variable for setInterval
	var time = setInterval(()=>{
		console.log('['+arr[i]+','+i+']');
		i++; 
		if(i==arr.length){
			this.clearInterval(time);// clear the interval after the index
		}
		}, interval);
}

callInterval();

于 2018-08-23T16:14:02.113 回答