我希望我的for循环不应该立即执行,而是在每次迭代后等待超时。例如:
for(var i=0; i<10; i++) {
console.log(i);
//wait for 1000
}
我发现堆栈溢出的许多解决方案都像这样:
for (var i=0;i<=10;i++) {
(function(ind) {
setTimeout(function(){console.log(ind);}, 3000);
})(i);
}
但是在所有实现中,循环最初等待3000毫秒,然后立即执行整个for
循环。有没有办法在等待1000毫秒后调用每个迭代。
答案 0 :(得分:30)
你可以用简单的数学方法解决这个问题:
for (var i=0;i<=10;i++) {
(function(ind) {
setTimeout(function(){console.log(ind);}, 1000 + (3000 * ind));
})(i);
}
1000ms:0
4000ms:1
7000ms:2
10000ms:3
13000ms:4
...
您的请求似乎有点模糊。如果您想在上次超时后执行某些操作,可以设置限制并比较当前索引:
var limit = 10
for (var i=0;i<=limit;i++) {
(function(ind) {
setTimeout(function(){
console.log(ind);
if(ind === limit){
console.log('It was the last one');
}
}, 1000 + (3000 * ind));
})(i);
}
小提琴:http://jsfiddle.net/Tn4A7/
只是做
for (var i=0;i<=10;i++) {
(function(ind) {
setTimeout(function(){console.log(ind);}, 1000 * ind);
})(i);
}
答案 1 :(得分:13)
不要在循环中创建函数,而是:
(function fiveSeconds (n) {
if (n < 5) setTimeout(function () {
fiveSeconds ( n ); // Redo if n < 5 (and pass n)
}, 1000);
console.log( n++ );
} (0)); // Initialize. n is 0
&#13;
以上将以1 - 5秒的间隔从0 - 5记录十个数字。
(function fiveSeconds (n) {
console.log( n++ );
if (n <= 5) setTimeout( fiveSeconds, 1000, n ); // Redo if n <= 5 (and pass n)
} (0)); // Initialize. n is 0
&#13;
答案 2 :(得分:6)
为什么不使用这样的东西:
var i = 0
var id = window.setInterval(function(){
if(i >= 10) {
clearInterval(id);
return;
}
console.log(i);
i++;
}, 1000)
答案 3 :(得分:3)
这有效:
function initiateTimeOut(i) {
setTimeout(function() { doStuff(i) }, 30);
}
function doStuff(i) {
console.log(i);
i++;
if (i <= 10) {
initiateTimeOut(i);
}
}
initiateTimeOut(0);
这样你只会在你的功能执行时递增i
,我相信这就是你要找的东西。
小提琴中的示例: http://jsfiddle.net/My7Zg/
或者,甚至更短( http://jsfiddle.net/My7Zg/1/ ):
function customLoop(i) {
console.log(i);
i++;
if (i<=10) {setTimeout(function(){customLoop(i);},1000);}
}
customLoop(0);
答案 4 :(得分:1)
for (var i=0;i<=10;i++) {
(function(ind) {
setTimeout(function(){console.log((ind + 1)*1000, ':', ind);}, 1000 * (ind+1) );
})(i);
}
输出:
1000 : 0
2000 : 1
3000 : 2
4000 : 3
5000 : 4
6000 : 5
7000 : 6
8000 : 7
9000 : 8
10000 : 9
11000 : 10
答案 5 :(得分:1)
您可以通过两种方式处理您的情况。
您可以随时安排一大堆setTimeout()
次呼叫,以便将来在所需的时间执行(此处的其他答案说明了如何执行此操作)。
您可以执行第一次迭代,安排下一次迭代并执行下一次迭代计划,然后完成所需的迭代次数。这最终比设置大量setTimeout()
调用更具可伸缩性,并为您提供更多的分支/逻辑自由,因为您可以控制每次迭代后接下来发生的事情。
使用更通用的实用程序功能的第二个选项如下所示:
// utility function to call a callback numTimes,
// separated by delay milliseconds
function runIteration(fn, numTimes, delay) {
var cnt = 0;
function next() {
// call the callback and stop iterating if it returns false
if (fn(cnt) === false) return;
++cnt;
// if not finished with desired number of iterations,
// schedule the next iteration
if (cnt < numTimes) {
setTimeout(next, delay);
}
}
// start first iteration
next();
}
因此,要执行您的控制台声明,您可以这样做:
runIteration(function(i) {
console.log(i);
}, 10, 1000);
工作演示:http://jsfiddle.net/jfriend00/HqCZ3/
这也可以通过第二个回调函数进行扩展,该函数在迭代完成时调用(在某些情况下很有用),或者它可以返回在迭代完成时解析的promise。
以下是返回承诺的版本:http://jsfiddle.net/jfriend00/XtJ69/
// utility function to call a callback numTimes,
// separated by delay milliseconds
function runIteration(fn, numTimes, delay) {
var d = $.Deferred();
var cnt = 0;
function end() {
d.resolve();
}
function next() {
// call the callback and stop iterating if
// it returns false
if (fn(cnt) === false) {
end();
return;
}
++cnt;
// if not finished with desired number of iterations,
// schedule the next iteration
if (cnt < numTimes) {
setTimeout(next, delay);
} else {
end();
}
}
// start first iteration
next();
return d.promise();
}
runIteration(function(i) {
log(i);
}, 10, 1000).done(function() {
log("done");
});
答案 6 :(得分:0)
这是一个简单超时的解决方案......也许它与你的期望不完全匹配,但试图做出一个&#34;暂停&#34;用javascript在我的建议中不是一个好方法。我建议你用另一种方式去做你想做的事。 Fiddle
window.my_condition = true;
window.my_i = 0;
function interate() {
console.log(window.my_i);
// ... your code
if (window.my_condition!==false) {
window.my_i++;
setTimeout(interate,300);
}
}
interate();
答案 7 :(得分:0)
这里的大多数答案都是完全错误的。
如果你想等待每次迭代完成---那么你不想使用for循环 - 只是错误的策略开始。
你需要使用计数器和计数器限制,否则它将无休止地循环。
这是解决方案:
var optionLimit = 11;
var optionItem = 1;
function do_something_else() {
if (optionItem < optionLimit) {
console.log('doing stuff:' + optionItem)
optionItem++
dostuff();
} else {
console.log('no more stuff to do already reached:' + optionItem)
}
}
function dostuff(started) {
if (started) {
console.log('started doing something');
} else {
console.log('find something else to do');
}
setTimeout(function () {
do_something_else();
}, 3000);
}
dostuff('started doing something');
如果您有一组需要索引的项目 - 那么您可以使用循环来计算需要执行的项目数量,如下所示:
var thingstodo = [
thing1 = {
what: 'clean room',
time: 8000
},
thing2 = {
what: 'laundry',
time: 9000
},
thing3 = {
what: 'take out trash',
time: 6000
},
thing4 = {
what: 'wash dishes',
time: 10000
}
]
var optionLimit = 0;
// find how many things to do from things to do list
function get_things_todo(time) {
console.log('heres stuff i can do');
console.log('====================');
for (var i = 0; i < thingstodo.length; i++) {
val = thingstodo[i];
console.log(JSON.stringify(val.what));
optionLimit++
}
setTimeout(function () {
startdostuff(3000)
}, time);
}
var optionItem = 0;
// find the next thing to do on the list
function get_next_thing(time) {
setTimeout(function () {
console.log('================================');
console.log('let me find the next thing to do');
}, time);
setTimeout(function () {
if (optionItem < optionLimit) {
val = thingstodo[optionItem];
dostuff(3000, val);
optionItem++
} else {
console.log('=====================================================');
console.log('no more stuff to do i finished everything on the list')
}
}, time*1.5);
}
//do stuff with a 3000ms delay
function dostuff(ftime, val) {
setTimeout(function () {
console.log('================================');
console.log('im gonna ' + JSON.stringify(val.what));
console.log('will finish in: ' + JSON.stringify(val.time) + ' milliseconds');
setTimeout(function () {
console.log('========');
console.log('all done');
get_next_thing(3000);
}, val.time);
}, ftime);
}
//start doing stuff
function startdostuff(time) {
console.log('========================');
console.log('just started doing stuff');
setTimeout(function () {
get_next_thing(3000);
}, time);
}
/// get things to first
get_things_todo(3000);
答案 8 :(得分:0)
这是一个var x = document.referrer;
if (x == "page2.html") {
console.log(x);
} else {
window.location.href = "login.html";
};
解决方案。我真的不喜欢在函数中包装es6
,只需使用这样的块作用域变量:
setTimeout
答案 9 :(得分:0)
我最好的工作方式是忘记正常循环&#34;在这种情况下,使用&#34; setInterval&#34;包括&#34; setTimeOut&#34; s:
function iAsk(lvl){
var i=0;
var intr =setInterval(function(){ // start the loop
i++; // increment it
if(i>lvl){ // check if the end round reached.
clearInterval(intr);
return;
}
setTimeout(function(){
$(".imag").prop("src",pPng); // do first bla bla bla after 50 millisecond
},50);
setTimeout(function(){
// do another bla bla bla after 100 millisecond.
seq[i-1]=(Math.ceil(Math.random()*4)).toString();
$("#hh").after('<br>'+i + ' : rand= '+(Math.ceil(Math.random()*4)).toString()+' > '+seq[i-1]);
$("#d"+seq[i-1]).prop("src",pGif);
var d =document.getElementById('aud');
d.play();
},100);
setTimeout(function(){
// keep adding bla bla bla till you done :)
$("#d"+seq[i-1]).prop("src",pPng);
},900);
},1000); // loop waiting time must be >= 900 (biggest timeOut for inside actions)
}
PS:理解(setTimeOut)的真实行为:它们都将在同一时间开始&#34;三个bla bla bla将在同一时刻开始倒计时#34;所以要做一个不同的超时来安排执行。
PS 2:定时循环的示例,但对于反应循环,您可以使用事件,承诺异步等待..
答案 10 :(得分:0)
我分享了一个简单的解决方案。
要解决这个问题,您需要使用闭包:立即调用将在每次迭代中调用的函数,并在此函数内以“i”作为参数和 setTimeout。在这种情况下,您传递的参数将存储在作用域中并可用于超时回调:
for (var i=1; i<6; i++) (function(t) {
setTimeout(function() {
//do anything with t
}, t*1000)
}(i))
通过此示例,您将大致了解该函数会发生什么:
for (var i=1; i<6; i++) (function(t) {
setTimeout(function() {
console.log(t);
}, t*1000)
}(i))
答案 11 :(得分:0)
另一种解决方法是将 generator function
与 setInterval
一起使用:
const steps = function*() {
for (let i=0; i<10; i++) {
yield i;
}
}
const step = steps();
setInterval(function(){
console.log(step.next().value)
}, 1000);