admin管理员组文章数量:1415458
I'm trying to run multiple setInterval()
's but I'm having trouble with the asynchronous aspect of doing this.
This example is almost identical to what I'm trying to achieve:
var labels = ["Bacon", "Beer", "Steak"];
var second, timer;
labels.forEach(function(label){
second = 0;
timer = setInterval(function(){
console.log(label + ' is awesome ' + second);
if(second === 10) {
clearInterval(timer);
}
second++;
}, 1000);
});
Because of setInterval being asynchronous the three intervals are running in parallel and are messing up the interval:
Bacon is awesome 0
Beer is awesome 1
Steak is awesome 2
Beer is awesome 3
Bacon is awesome 4
Steak is awesome 5
Bacon is awesome 6
Beer is awesome 7
Steak is awesome 8
Bacon is awesome 9
Beer is awesome 10
Beer is awesome 11
Bacon is awesome 12
Beer is awesome 13
Bacon is awesome 14
Bacon is awesome 15
Beer is awesome 16
Beer is awesome 17
Bacon is awesome 18
Bacon is awesome 19
Beer is awesome 20
Beer is awesome 21
Bacon is awesome 22
Bacon is awesome 23
...
I'm wondering how to enforce some sort of queue so that the first interval runs it's course then when 10 seconds are up the next setInterval is executed?
I've tried quickly with the async.js library but I had trouble finding a suitable control flow.
I'm trying to run multiple setInterval()
's but I'm having trouble with the asynchronous aspect of doing this.
This example is almost identical to what I'm trying to achieve:
var labels = ["Bacon", "Beer", "Steak"];
var second, timer;
labels.forEach(function(label){
second = 0;
timer = setInterval(function(){
console.log(label + ' is awesome ' + second);
if(second === 10) {
clearInterval(timer);
}
second++;
}, 1000);
});
Because of setInterval being asynchronous the three intervals are running in parallel and are messing up the interval:
Bacon is awesome 0
Beer is awesome 1
Steak is awesome 2
Beer is awesome 3
Bacon is awesome 4
Steak is awesome 5
Bacon is awesome 6
Beer is awesome 7
Steak is awesome 8
Bacon is awesome 9
Beer is awesome 10
Beer is awesome 11
Bacon is awesome 12
Beer is awesome 13
Bacon is awesome 14
Bacon is awesome 15
Beer is awesome 16
Beer is awesome 17
Bacon is awesome 18
Bacon is awesome 19
Beer is awesome 20
Beer is awesome 21
Bacon is awesome 22
Bacon is awesome 23
...
I'm wondering how to enforce some sort of queue so that the first interval runs it's course then when 10 seconds are up the next setInterval is executed?
I've tried quickly with the async.js library but I had trouble finding a suitable control flow.
Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Mar 14, 2014 at 18:02 iamjonesyiamjonesy 25.1k42 gold badges145 silver badges206 bronze badges 4- setInterval() isn't asynchronous – Amit Joki Commented Mar 14, 2014 at 18:06
- 1 Can you add your desired output to the question? – Kelvin Commented Mar 14, 2014 at 18:09
- Yes, the desired output would be nice – Moritz Roessler Commented Mar 14, 2014 at 18:47
- Hey sorry for delay. Desired output would be: Bacon is awesome 0, bacon is awesome 1..10, then beer is awesome 0, beer is awesome 1..10 – iamjonesy Commented Mar 15, 2014 at 1:12
4 Answers
Reset to default 2I made a little function called `callQueue' that calls an Array filled with functions in order a certain number of times with a certain interval between them
Usage
The first argument is the array of functions, the second the number of times they should be called, the third is the time between the calls.
callQueue([
function () {
isAwesome('bacon');
},
function () {
isAwesome('beer');
},
function () {
isAwesome('steak');
}], 10, 1000);
The Function
function callQueue(queue, times, timeBetween) {
var i = 0;
k = 0;
queue.forEach(function (func) {
for (k = 0; k < times; k += 1) {
alert(i * timeBetween);
i += 1;
setTimeout(func, (i * timeBetween));
}
});
};
Demo: http://jsfiddle/howderek/L5nhU/
This was good for me to practice some OO style Javascript :)
function Timer(name) {
var self = this;
this.name = name;
this.count = 0;
this.x = setInterval(function () {
if (self.count++ == 9) {
clearInterval(self.x);
}
console.log(self.name + ' ' + self.count + ' is awesome');
}, 1000);
}
var labels = ["Bacon", "Beer", "Steak"];
labels.forEach(function (label) {
new Timer(label);
});
Demo
You could e.g. use setTimeout
without a loop at all, and pick the right label from within the function.
var labels = ["Bacon", "Beer", "Steak"],
steps = 10,
total = 0,
step = 0,
sequence = 0,
label = labels [0];
(function fn (){
if (step === steps && sequence === labels.length - 1) {
return;
} else if(step === steps) {
label = labels [++sequence];
step = 0;
}
console.log(label + ' is awesome ' + total);
step++;
total++;
setTimeout (fn, 1000)
})();
Fiddle
Or e.g. keep the loop and use the index and your number of steps as multiplier as timeout, to delay the other timeouts accordingly.
var labels = ["Bacon", "Beer", "Steak"],
steps = 10,
total = 0;
labels.forEach(function(label, index){
var step = 0;
setTimeout (function fn (){
if(step === steps) {
return;
}
console.log(label + ' is awesome ' + total);
step++;
total++;
setTimeout (fn, 1000)
},( (steps + 1)* index ) * 1000);
});
Fiddle
Or wrap your setInterval
in a setTimeout
.
var labels = ["Bacon", "Beer", "Steak"];
labels.forEach(function(label, index){
setTimeout (function () {
var second = 0;
var timer = setInterval(function(){
console.log(label + ' is awesome ' + second);
if(second === 10) {
clearInterval(timer);
}
second++;
}, 1000);
},index * 11 * 1000);
});
Fiddle
All produce
Bacon is awesome 0
Bacon is awesome 1
Bacon is awesome 2
Bacon is awesome 3
Bacon is awesome 4
Bacon is awesome 5
Bacon is awesome 6
Bacon is awesome 7
Bacon is awesome 8
Bacon is awesome 9
Beer is awesome 0
Beer is awesome 1
Beer is awesome 2
Beer is awesome 3
...
Once you've called setInterval
and setTimeout
you're in the hands of the browser; the time that passes isn't guaranteed to be exact and the order that multiple callbacks are executed in aren't guaranteed to be exact - and usually won't be.
If you want to enforce order of execution, using setTimeout
instead of setInterval
will give you the opportunity to decide what happens when each callback pletes.
Here's a fiddle that iterates over the Bacons first, then Beers, then Steaks: http://jsfiddle/q96Vc/
And here's one that displays each label one after the other until 30 seconds is up: http://jsfiddle/DtbZ6/1/
You could even expand on either of these examples to use three separate calls to setTimeout
that won't get repeated until the three previous calls have all been executed, which would mean the order of the three would vary but they would never overlap.
本文标签: javascriptSequentially running multiple setIntervalsStack Overflow
版权声明:本文标题:javascript - Sequentially running multiple setIntervals - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745181338a2646479.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论