I want to backup, delete every item in a list, and append each one after 1 second.
I am trying like this:
var backup = $('#rGallery').html();
$('#rGallery li').remove();
console.log($(backup).filter('li').length); /* it logs like 135 */
$(backup).filter('li').each(function(){
var the = $(this);
var timeout = setTimeout(function(){
console.log(the.html()); /* it logs the html, but all at the same time*/
$('#rGallery').append('<li>'+the.html()+'</li>');
/*return*/
},1000);
});
Its works, items are removed and then append'ed again, problem is that they're all being appended after 1 second. Instead of each one to wait 1 second from the previous one.
What am I missing here?
Because you are telling them all to run in one second, they are not added to some magic queue and wait in line to start counting.
$(backup).filter('li').each(function(index){ //added index here
var the = $(this);
var timeout = setTimeout(function(){
console.log(the.html()); /* it logs the html, but all at the same time*/
$('#rGallery').append('<li>'+the.html()+'</li>');
/*return*/
},1000*(index+1)); //multiplied it here
});
setTimeout isn't blocking; it schedules the timeout, then continues. Therefore the next iteration of each() happens immediately, which schedules the next element for exactly the same time (etc).
You should therefore change your code like such (one approach), which runs the function every 1000ms, adding the next element to backup.
var backup = $('#rGallery li');
var i = 0;
$('#rGallery li').remove();
var interval = setInterval(function () {
if (i === backup.length) {
clearInterval(interval);
} else {
var the = $(backup).eq(i);
$('#rGallery').append('<li>'+the.html()+'</li>');
}
i++;
}, 1000);
Related
I am trying to create a timer that every second it does calls another function. So I am using setInterval within a for loop.
The setInterval is being skipped during the first loop through in the for loop.
Not sure why.
Also,
I have the function to clear the Interval when it goes below zero. When I have a message printing within the stopping condition, that outputs but the clearInterval is skipped.
function changesystem(lottery, maxroundtime, firstloop) {
//loop through lottery numbers
for (var keys in lottery) {
var currentnum = lottery[keys].LotteryNum;
console.log(currentnum);
var currentclass = lottery[keys].ClassID;
//console.log(currentclass);
//display values
$('#CurrentNumber').text(currentnum);
$('#CurrentClass').text(currentclass);
//change progress bar
//every second until reaches max round time
// var loopcontrol = maxroundtime;
var loopcontrol = 5;
var timerloop = setInterval(function() {
console.log(loopcontrol);
//changetime(maxroundtime,firstloop);
loopcontrol--;
//firstloop=1;
}, 1000);
if (loopcontrol < 0) {
clearInterval(timerloop);
}
}
Visual Example
You need to take into account that asynchronous code does not stop the current execution-code. The callback function you pass to setInterval is called asynchronously, i.e. after the currently being executed code has finished until the point the call-stack is empty.
So setInterval does not wait somehow for the seconds to pass. The for loop will go through all iterations immediately, having created just as many setInterval timers, which all start to tick afterwards, and will continue to do so for ever. The clearInterval code will never get executed.
Here is how you could do it, making use of asynchronous "loops", i.e. with functions that that get called several times, asynchronously.
function changesystem(lottery,maxroundtime,firstloop){
//loop asynchronously through lottery numbers
(function loop(keys) {
if (!keys.length) return; // all done
var key = keys.shift(); // extract next key
var currentnum = lottery[key].LotteryNum;
console.log('lottery number', currentnum);
var currentclass = lottery[key].ClassID;
//display values
$('#CurrentNumber').text(currentnum);
$('#CurrentClass').text(currentclass);
//change progress bar asynchronously
//every second until reaches max round time
(function progress(loopControl) {
console.log('loopControl', loopControl);
if (!loopControl) {
loop(keys); // done: continue with next lottery number
} else { // schedule next progress tick
setTimeout(progress.bind(null, loopControl-1), 1000);
}
})(5); // start with loopControl 5
})(Object.keys(lottery)); // pass all keys
}
I am writing an application that has to take audio input of a certain frequency range and increase the counter variable till clock ticks x seconds after the browser starts taking the input. I have done most of it but the problem is the loop with input. for example if I want to take frequency level 10 or above, and write following code
if (f>10) {
var count=0;
count++;
}
the code increases count only once. But I want to increase it based on the sound til x seconds. If I use while loop the scripts stops responding.
The while loop is synchronous. You'll need to use an asynchronous loop. You have a couple options for this:
Use a setTimeout and put your while loop in that and use a callback when it gets finished
Use a setInterval.
var loop = function(f, callback){
setTimeout(function(){
var count=0;
while(f>10){
count++;
}
callback(count);
}, 0);
};
or
var loop = function(f, callback){
var count = 0;
var si = setInterval(function(){
count++
if(f<=10){
clearInterval(si);
callback(count);
}
}, 1000);
};
Using these functions:
loop(frequencyVariable, function(count){
//callback has been called successfully and the loop has ended.
//do stuff here
});
How to skip a one step in jquery setInterval function
e.g
<script>
// start updating continuously
var timer, delay = 3000; // time in milli seconds
timer = setInterval(function(){
// do something for each iteration
// I want to do this only once
if(result["pass"]){
$("#test").append("<li>Passed</li>");
}
// do something for each iteration
}, delay);
</script>
how can I skip one or more than one steps to happen if they are happened once.
I want to skip only when it happens once. e.g if the condition is true in 101st iteration then it will not happen in first 100 iterations but if condition is still true in 102nd iteration, it should not happen because it happens in 101st iteration.
Any help would be much appreciated.
<script>
// start updating continuously
var timer, delay = 3000; // time in milli seconds
var alreadyAdded=false;
timer = setInterval(function(){
// do something for each iteration
// I want to do this only once
if(!alreadyAdded && result["pass"]){
$("#test").append("<li>Passed</li>");
alreadyAdded=true;
}
// do something for each iteration
}, delay);
</script>
This is a good example of where you can use a closure. You can create a function that returns a function.
This allows you to declare a variable in the scope of the outer function, which can then be accessed by the inner function.
function getIntervalHandler() {
var hasPassed = false;
return function() {
if(!hasPassed) {
if(result["pass"]){
$("#test").append("<li>Passed</li>");
hasPassed = true;
}
}
};
}
timer = setInterval(getIntervalHandler(), delay);
Just like continue is used to break current iteration and proceed with the next, how can I break current iteration within setInterval() in JavaScript and proceed with the next interval without waiting?
var intervalID = window.setInterval( function() {
if(conditionIsTrue) {
// Break this iteration and proceed with the next
// without waiting for 3 seconds.
}
}, 3000 );
You could "simply" (or not so simply) clear the interval, and re-create it:
// run the interval function immediately, then start the interval
var restartInterval = function() {
intervalFunction();
intervalID = setInterval(intervalFunction, 3000 );
};
// the function to run each interval
var intervalFunction = function() {
if(conditionIsTrue) {
// Break this iteration and proceed with the next
// without waiting for 3 seconds.
clearInterval(intervalID);
restartInterval();
}
};
// kick-off
var intervalID = window.setInterval(intervalFunction, 3000 );
Here's a demo/test Fiddle.
Just tested this, and it acts as a continue statement in a loop. For fellow coders finding this now, just use return within the setInterval.
var myRepeater = setInterval( function() {
if(conditionIsTrue) {
return;
}
}, 1000 );
EDIT: To comply with the immediate execution after breaking the current execution of the loop, one could instead do something like so (in theory. And beware of recursion issues if conditionIsTrue stays true):
function myFunction() {
if(conditionIsTrue) {
myFunction();
return;
}
// Interval function code here...
}
var myRepeater = setInterval( myFunction, 1000 );
fourI am writing a javascript for loop and am sure have done a terrible job:
init = function () {
var i = 0;
timer = setInterval(function () {
if (i >= 4) {
clearInterval(timer);
return;
}
for (i = 0; i < 10; i++) {
console.log('init fired');
}
}, 2000);
};
init();
What I want is for the timer to stop after the i variable in the for loop reaches four. Instead the log is showing init fired ten times. What am I doing wrong?
I think you need it like this
var i=0; //Global Declaration
init = function(){
timer = setInterval(function(){
console.log('init fired');
i++;
if(i>4){
clearInterval(timer);
return; }
}, 2000);
};
init();
Hope this solves your problem. This will trigger init() method four times as you have expected and if the i reaches 4 the interval will be cleared.
Every time the timeout handler runs, it starts "i" back at zero.
The problem with your "for" loop is basically that you should not use a "for" loop :-)
Those 10 iterations are happening on the first pass through the function. After that first pass, "i" will be 10 and so the "if" condition will cancel the timeout. However, that "if" check is only made at the beginning of the function, so the loop will always complete 10 iterations.
If you want to have just four iterations of the timer (or five or whatever), you'd just leave off the "for" loop, and add i++; after the console log message. That way, the timer would issue one log output when it runs, and when that's happened the number of times you desire, it will stop.