oli*_*dev 313 javascript sleep loops
我想在while
循环中添加延迟/睡眠:
我试过这样的:
alert('hi');
for(var start = 1; start < 10; start++) {
setTimeout(function () {
alert('hello');
}, 3000);
}
Run Code Online (Sandbox Code Playgroud)
只有第一种情况是真的:显示后alert('hi')
,它将等待3秒然后alert('hello')
将显示,但随后alert('hello')
将反复不断.
我想要的是,在alert('hello')
3秒之后显示alert('hi')
之后,它需要等待第二次3秒alert('hello')
,依此类推.
Dan*_*llo 705
该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
alert('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
Run Code Online (Sandbox Code Playgroud)
您也可以通过使用自调用函数将迭代次数作为参数传递来消除它:
(function myLoop (i) {
setTimeout(function () {
alert('hello'); // your code here
if (--i) myLoop(i); // decrement i and call myLoop again if i > 0
}, 3000)
})(10); // pass the number of iterations as an argument
Run Code Online (Sandbox Code Playgroud)
cji*_*cji 69
尝试这样的事情:
var i = 0, howManyTimes = 10;
function f() {
alert( "hi" );
i++;
if( i < howManyTimes ){
setTimeout( f, 3000 );
}
}
f();
Run Code Online (Sandbox Code Playgroud)
Sak*_*hta 61
如果使用ES6,您可以使用let
以实现此目的:
for (let i=1; i<10; i++) {
setTimeout( function timer(){
alert("hello world");
}, i*3000 );
}
Run Code Online (Sandbox Code Playgroud)
为每次迭代let
声明i
了什么,而不是循环.这样,传递的内容正是我们想要的.setTimeout
Jon*_*lms 41
由于ES7是等待循环的更好方法:
// Returns a Promise that resolves after "ms" Milliseconds
function timer(ms) {
return 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();
Run Code Online (Sandbox Code Playgroud)
请注意,今天很少支持ES7,因此您需要与Babel进行交互,以便在任何地方使用它.
Fel*_*ing 21
另一种方法是将时间乘以超时,但请注意,这与睡眠不同.循环后的代码将立即执行,只延迟执行回调函数.
for (var start = 1; start < 10; start++)
setTimeout(function () { alert('hello'); }, 3000 * start);
Run Code Online (Sandbox Code Playgroud)
第一个超时将设置为3000 * 1
,第二个超时将设置为3000 * 2
依此类推.
小智 21
您可以创建一个sleep
承诺的函数setTimeout
。这使您能够使用async
/await
编写代码,而无需回调和熟悉的for
循环控制流。
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
(async () => {
for (let i = 0; i < 10; i++) {
console.log(i);
await sleep(1000);
}
console.log("done");
})();
Run Code Online (Sandbox Code Playgroud)
在 Node 中,您可以使用timers/promises
以避免 Promisification 步骤(如果您的旧 Node 版本不支持该功能,则上述代码也同样有效):
const {setTimeout: sleep} = require("timers/promises");
// same code as above
Run Code Online (Sandbox Code Playgroud)
无论如何,由于 JS 是单线程的,所以超时是异步的是一件好事。如果不是,浏览器将没有机会重新绘制 UI,从而导致用户界面冻结。
BGe*_*sen 15
我想你需要这样的东西:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
测试代码:
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();
Run Code Online (Sandbox Code Playgroud)
注意:使用警报会停止javascript执行,直到您关闭警报.它可能比您要求的代码更多,但这是一个强大的可重用解决方案.
Abe*_*efe 14
我可能会用setInteval
.像这样,
var period = 1000; // ms
var endTime = 10000; // ms
var counter = 0;
var sleepyAlert = setInterval(function(){
alert('Hello');
if(counter === endTime){
clearInterval(sleepyAlert);
}
counter += period;
}, period);
Run Code Online (Sandbox Code Playgroud)
小智 14
这会奏效
for (var i = 0; i < 10; i++) {
(function(i) {
setTimeout(function() { console.log(i); }, 100 * i);
})(i);
}
Run Code Online (Sandbox Code Playgroud)
试试这个小提琴:https://jsfiddle.net/wgdx8zqq/
小智 13
在我看来,在循环中添加延迟的更简单、最优雅的方法是这样的:
names = ['John', 'Ana', 'Mary'];
names.forEach((name, i) => {
setTimeout(() => {
console.log(name);
}, i * 1000); // one sec interval
});
Run Code Online (Sandbox Code Playgroud)
在ES6(ECMAScript 2015)中,您可以使用生成器和间隔进行延迟迭代.
生成器,ECMAScript 6的一个新功能,是可以暂停和恢复的功能.调用genFunc不会执行它.相反,它返回一个所谓的生成器对象,让我们控制genFunc的执行.genFunc()最初在其正文的开头被暂停.genObj.next()方法继续执行genFunc,直到下一个yield. (探索ES6)
代码示例:
let arr = [1, 2, 3, 'b'];
let genObj = genFunc();
let val = genObj.next();
console.log(val.value);
let interval = setInterval(() => {
val = genObj.next();
if (val.done) {
clearInterval(interval);
} else {
console.log(val.value);
}
}, 1000);
function* genFunc() {
for(let item of arr) {
yield item;
}
}
Run Code Online (Sandbox Code Playgroud)
所以如果你正在使用ES6,这是实现延迟循环的最优雅方式(对于我的看法).
await new Promise((resolve) => {setTimeout(() => {resolve(true)}, 190)});
Run Code Online (Sandbox Code Playgroud)
异步函数内的实际延迟,作为常用的具有setTimeout
不同超时间隔的多个 s 的替代方案,这可能会弄乱内存。对于此片段,延迟为 190 毫秒。
例子:
await
都有一个new Promise
to resolve
。setTimeout
在 190 毫秒后“允许”后才会发生。在此之前,代码会被 async-await /ending 阻塞Promise
。await new Promise((resolve) => {setTimeout(() => {resolve(true)}, 190)});
Run Code Online (Sandbox Code Playgroud)
我用 BluebirdPromise.delay
和递归来做到这一点。
function myLoop(i) {
return Promise.delay(1000)
.then(function() {
if (i > 0) {
alert('hello');
return myLoop(i -= 1);
}
});
}
myLoop(3);
Run Code Online (Sandbox Code Playgroud)
<script src="//cdnjs.cloudflare.com/ajax/libs/bluebird/2.9.4/bluebird.min.js"></script>
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
398008 次 |
最近记录: |