我对使用setTimeout和每个迭代器感到困惑。如何重写以下内容,以便控制台在延迟5秒后输出每个名称?目前,以下代码在5秒后立即打印所有名称。我想:
1)等待5秒钟,然后打印凯文
2)等待5秒钟,然后打印迈克
3)等待5秒,然后打印莎莉
var ary = ['kevin', 'mike', 'sally'];
_(ary).each(function(person){
setTimeout(function(){
console.log(person);
}, 5000);
});
答案 0 :(得分:10)
您可以创建一个名为offset
的变量,使计时器等待阵列中的每个人等待5秒钟,如下所示:
var ary = ['kevin', 'mike', 'sally'];
var offset = 0;
_(ary).each(function(person){
setTimeout(function(){
console.log(person);
}, 5000 + offset);
offset += 5000;
});
答案 1 :(得分:7)
setTimeout
setTimeout
+条件递归 setInterval
+条件clearInterval
在这里,每个人都充实了一个充实的例子:
setTimeout
关于这一个的几个注意事项。这有点像开始接力赛并提前向每个跑步者发出指令,准确地在5:00和5:02以及5:04开始,无论他们背后的人是很久以前完成还是没有&#但尚未抵达。
此外,您不能使用常规for i=0 loop
,因为for运算符未定义新的函数范围。因此,在每个for循环中设置的对象值将适用于迭代。调用setTimeout时,它将仅使用最新值。所以我们需要一个闭包来存储每个循环中的值。我已经使用了Array.prototype.forEach()
,但如果您想在jQuery或Underscore中使用forEach实现,那么它也可以使用。
function ArrayPlusDelay(array, delegate, delay) {
// initialize all calls right away
array.forEach(function (el, i) {
setTimeout(function() {
// each loop, call passed in function
delegate( array[i]);
// stagger the timeout for each loop by the index
}, i * delay);
})
}
// call like this
ArrayPlusDelay(['a','b','c'], function(obj) {console.log(obj)},1000)

setTimeout
+条件递归对于最下面两个选项,我们正在制作自己的循环,因此我们必须自己跟踪索引,初始化为零并在整个过程中递增。
对于这个,我们a)a)调用setTimeout
,它将运行一次,b)在索引位置评估数组,c)检查数组中是否有更多元素,如果是,从(a)开始。
function ArrayPlusDelay(array, delegate, delay) {
var i = 0
function loop() {
// each loop, call passed in function
delegate(array[i]);
// increment, and if we're still here, call again
if (i++ < array.length - 1)
setTimeout(loop, delay); //recursive
}
// seed first call
setTimeout(loop, delay);
}
// call like this
ArrayPlusDelay(['d','e','f'], function(obj) {console.log(obj)},1000)
&#13;
setInterval
+条件clearInterval
注意:函数setInterval
将在调用后永久运行。它在初始设置时的返回值将提供对间隔的引用,因此它通常与函数clearInterval
结合使用,以便可选地将其关闭在路上
function ArrayPlusDelay(array, delegate, delay) {
var i = 0
// seed first call and store interval (to clear later)
var interval = setInterval(function() {
// each loop, call passed in function
delegate(array[i]);
// increment, and if we're past array, clear interval
if (i++ >= array.length - 1)
clearInterval(interval);
}, delay)
}
ArrayPlusDelay(['x','y','z'], function(obj) {console.log(obj)},1000)
&#13;
选项1&amp; 2是有风险的,因为一旦你启动了那列火车,就无法在路上取消它(除了关闭浏览器)。如果你的代表中有一个大型数组或一个重负载,如果你需要它可能会提供一些追索权。通过保存setInterval
的引用,我们可以持续访问迭代函数。我们只需要返回上面的interval对象并在调用我们的数组加延迟函数时保存它。
function ArrayPlusDelay(array, delegate, delay) {
var i = 0
// seed first call and store interval (to clear later)
var interval = setInterval(function() {
// each loop, call passed in function
delegate(array[i]);
// increment, and if we're past array, clear interval
if (i++ >= array.length - 1)
clearInterval(interval);
}, delay)
return interval
}
var inter = ArrayPlusDelay(['x','y','z'], function(obj) {console.log(obj)},1000)
&#13;
然后,如果我们以后想要清除它,只需将其抛入控制台:
clearInterval(inter);
答案 2 :(得分:6)
你可以做到
var ary = ['kevin', 'mike', 'sally'];
_(ary).each(function(person, index){
setTimeout(function(){
console.log(person);
}, index * 5000);
});
如果不增加timeout
值,您可以使用完全相同的值初始化所有setTimeouts
(这就是您看到所见内容的原因)。
答案 3 :(得分:1)
each
通常会更好。
相反,如果您不介意更改数组,可以将其用作队列:
var ary = ['kevin', 'mike', 'sally'];
setTimeout(function loop() {
console.log(ary.shift());
if (ary.length)
setTimeout(loop, 5000);
}, 5000);
将来会继续调用loop
5秒,直到队列中没有任何内容。
答案 4 :(得分:0)
array.forEach接受一个回调函数,这意味着它已经创建了一个新的函数范围,并且由于setTimeout的性质是非阻塞的,因此立即返回,您只需要为每次迭代增加回调函数执行的延迟即可。
var ary = ['kevin', 'mike', 'sally'];
ary.forEach(function(person, index){
setTimeout(function(){
console.log(person);
}, 5000 * (index + 1));
})
如果要在for循环中实现相同效果,可以使用IIFE或let关键字
IIFE示例:
var ary = ['kevin', 'mike', 'sally'];
for(var i = 1; i <= ary.length; i++){
(function(i){
setTimeout(function(){
console.log(ary[i - 1]);
}, 5000 * i);
})(i)
}
让关键字示例:[ECMAScript 6]
var ary = ['kevin', 'mike', 'sally'];
for(let i = 1; i <= ary.length; i++){
setTimeout(function(){
console.log(ary[i - 1]);
}, 5000 * i);
}
答案 5 :(得分:-1)
你可以使用setInterval()和一个简单的逐个计数器。
var ary = ['kevin', 'mike', 'sally'];
var i=0;
setInterval(function(){
console.log(ary[i]);
i++;
}, 5000);
但请注意,这将在我变为大于2之后开始抛出错误。您需要在那里进行某种验证,并确保清除间隔。