我想在while循环中添加一个delay/sleep:
我是这样试的:
alert('hi');
for(var start = 1; start < 10; start++) {
setTimeout(function () {
alert('hello');
}, 3000);
}
只有第一种情况是正确的:在显示alert('hi')后,它将等待3秒,然后alert('hello')将显示,但随后alert('hello')将不断重复。
我想要的是,在警报('hello')显示3秒后警报('hi'),然后它需要等待3秒的第二次警报('hello'),以此类推。
除了10年前接受的答案之外,使用更现代的Javascript,可以使用async/await/Promise()或生成器函数来实现正确的行为。(其他答案中建议的错误行为是设置一系列3秒警报,而不管“接受”警报()-或完成手头的任务)
使用异步/等待/承诺():
alert('嗨');
(async () => {
For (let start = 1;起始值< 10;开始+ +){
等待新的承诺(resolve => setTimeout(() => {
alert('你好');
解决();
}, 3000));
}
}) ();
使用生成器函数:
警报(“嗨”);
让函子;
(func = (function*() {
for(let start = 1, start < 10, start++) {
yield setTimeout(() => {
警报(“你好”);
func.next();
}, 3000);
}
})()).next();
setTimeout()函数是非阻塞的,将立即返回。因此,您的循环将非常快速地迭代,它将快速连续地启动一个接一个的3秒超时触发器。这就是为什么你的第一个警告会在3秒后弹出,而所有其他的警告都会紧随其后,没有任何延迟。
你可能想用这样的东西代替:
var i = 1; // set your counter to 1
function myLoop() { // create a loop function
setTimeout(function() { // call a 3s setTimeout when the loop is called
console.log('hello'); // your code here
i++; // increment the counter
if (i < 10) { // if the counter < 10, call the loop function
myLoop(); // .. again which will trigger another
} // .. setTimeout()
}, 3000)
}
myLoop(); // start the loop
你也可以通过使用一个自调用函数,将迭代次数作为参数传递给它:
(函数myLoop(i) {
setTimeout(函数(){
console.log('你好');//你的代码
if(——i) myLoop(i);//减少i,如果i > 0再次调用myLoop
}, 3000)
}) (10);//传递迭代次数作为参数
因为ES7有一个更好的方法来等待循环:
// Returns a Promise that resolves after "ms" Milliseconds
const timer = ms => new Promise(res => setTimeout(res, ms))
async function load () { // We need to wrap the loop into an async function for this to work
for (var i = 0; i < 3; i++) {
console.log(i);
await timer(3000); // then the created Promise can be awaited
}
}
load();
当引擎到达await部分时,它设置一个超时并停止async函数的执行。然后,当超时完成时,继续执行。这是非常有用的,因为你可以延迟(1)嵌套循环,(2)有条件的,(3)嵌套函数:
异步函数任务(i) {// 3
等待计时器(1000);
console.log('任务${i}完成! ');
}
异步函数main() {
对于(设I = 0;I < 100;I += 10) {
For(令j = 0;J < 10;j++) {// 1
如果(j % 2) {// 2
等待任务(i + j);
}
}
}
}
main ();
函数定时器(ms){返回新的承诺(res => setTimeout(res, ms));}
MDN参考资料
虽然ES7现在被NodeJS和现代浏览器支持,但你可能想用BabelJS编译它,这样它就可以在任何地方运行。
我认为你需要这样的东西:
var TimedQueue = function(defaultDelay){
this.queue = [];
this.index = 0;
this.defaultDelay = defaultDelay || 3000;
};
TimedQueue.prototype = {
add: function(fn, delay){
this.queue.push({
fn: fn,
delay: delay
});
},
run: function(index){
(index || index === 0) && (this.index = index);
this.next();
},
next: function(){
var self = this
, i = this.index++
, at = this.queue[i]
, next = this.queue[this.index]
if(!at) return;
at.fn();
next && setTimeout(function(){
self.next();
}, next.delay||this.defaultDelay);
},
reset: function(){
this.index = 0;
}
}
测试代码:
var now = +new Date();
var x = new TimedQueue(2000);
x.add(function(){
console.log('hey');
console.log(+new Date() - now);
});
x.add(function(){
console.log('ho');
console.log(+new Date() - now);
}, 3000);
x.add(function(){
console.log('bye');
console.log(+new Date() - now);
});
x.run();
注意:使用警报暂停javascript执行,直到你关闭警报。
它的代码可能比您要求的要多,但这是一个健壮的可重用解决方案。