How to create pause or delay in FOR loop? - javascript

I am working on a website, where I need to create a pause or delay.
So please tell me How to create pause or delay in for loop in javascript or jQuery
This is a test example
var s = document.getElementById("div1");
for (i = 0; i < 10; i++) {
s.innerHTML = s.innerHTML + i.toString();
//create a pause of 2 seconds.
}

You can't use a delay in the function, because then the change that you do to the element would not show up until you exit the function.
Use the setTimeout to run pieces of code at a later time:
var s = document.getElementById("div1");
for (i = 0; i < 10; i++) {
// create a closure to preserve the value of "i"
(function(i){
window.setTimeout(function(){
s.innerHTML = s.innerHTML + i.toString();
}, i * 2000);
}(i));
}

var wonderfulFunction = function(i) {
var s = document.getElementById("div1"); //you could pass this element as a parameter as well
i = i || 0;
if(i < 10) {
s.innerHTML = s.innerHTML + i.toString();
i++;
//create a pause of 2 seconds.
setTimeout(function() { wonderfulFunction(i) }, 2000);
}
}
//first call
wonderfulFunction(); //or wonderfulFunction(0);
You can't pause javascript code, the whole language is made to work with events, the solution I provided let's you execute the function with some delay, but the execution never stops.

I tried all one, but I think this code is better one, it is very simple code.
var s = document.getElementById("div1");
var i = 0;
setInterval(function () {s.innerHTML = s.innerHTML + i.toString(); i++;}, 2000);

if you want to create pause or delay in FOR loop,the only real method is
while (true) {
if( new Date()-startTime >= 2000) {
break;
}
}
the startTime is the time before you run the while
but this method will cause the browsers become very slow

It is impossible to directly pause a Javascript function within a for loop then later resume at that point.

This is how you should do it
var i = 0;
setTimeout(function() {
s.innerHTML = s.innerHTML + i.toString();
i++;
},2000);

The following code is an example of pseudo-multithreading that you can do in JS, it's roughly an example of how you can delay each iteration of a loop:
var counter = 0;
// A single iteration of your loop
// log the current value of counter as an example
// then wait before doing the next iteration
function printCounter() {
console.log(counter);
counter++;
if (counter < 10)
setTimeout(printCounter, 1000);
}
// Start the loop
printCounter();

While several of the other answers would work, I find the code to be less elegant. The Frame.js library was designed to solve this problem exactly. Using Frame you could do it like this:
var s = document.getElementById("div1");
for (i = 0; i < 10; i++) {
Frame(2000, function(callback){ // each iteration would pause by 2 secs
s.innerHTML = s.innerHTML + i.toString();
callback();
});
}
Frame.start();
In this case, it is nearly the same as the examples that use setTimeout, but Frame offers a lot of advantages, especially if the you are trying to do multiple or nested timeouts, or have a larger JS application that the timeouts need to work within.

I am executing a function where I need access to the outside object properties. So, the closure in Guffa solution doesn't work for me. I found a variation of nicosantangelo solution by simply wrapping the setTimeout in an if statement so it doesn't run forever.
var i = 0;
function test(){
rootObj.arrayOfObj[i].someFunction();
i++;
if( i < rootObj.arrayOfObj.length ){
setTimeout(test, 50 ); //50ms delay
}
}
test();

The way I found was to simply use setInterval() to loop instead. Here's my code example :
var i = 0;
var inte = setInterval(() => {
doSomething();
if (i == 9) clearInterval(inte);
i++;
}, 1000);
function doSomething() {
console.log(i);
};
This loops from 0 to 9 waiting 1 second in between each iteration.
Output :
0 1 2 3 4 5 6 7 8 9

It is not possible to pause a loop. However you can delay the execution of code fragments with the setTimeout() function. It would not make a lot of sense to pause the entire execution anyway.

I am using while loop and check the pause variable to check the user pause/resume the code.
var pause = false;
(async () => {
for (let index = 0; index < 1000; index++) {
while (pause) {
await new Promise((res) => setTimeout(res, 1000));
console.log("waiting");
}
await new Promise((res) => setTimeout(res, 1000));
console.log(index);
}
})();
const pausefunc = async () => {
pause = true;
};
const playfunc = () => {
pause = false;
};
<button onclick="playfunc()">Play</button>
<button onclick="pausefunc()">Pause</button>

I used a do...while loop to put a delay in my code for a modal dialog that was closing too quickly.
your stuff....
var tNow = Date.now();
var dateDiff = 0;
do {
dateDiff = Date.now() - tNow;
} while (dateDiff < 1000); //milliseconds - 2000 = 2 seconds
your stuff....

Related

CSS Clip-Path Animation with Javascript

I try to animate the Clip-Path Property with JavaScript.
Means: It "grows" with help of SetTimeout.
I tried this, but it doesn't work.
http://jsfiddle.net/071dm2h3/8/
var el = document.getElementById("image")
function grow(i) {
el.style.clipPath = "circle("+ i +"px at 190px 160px)";
}
var i;
for(i = 0; i < 100; i++) {
setTimeout(grow(i), 400);
}
What am I missing here? Shouldn't the setTimeout change the value of I in every loop, so that I can see the result immediately?
To get this to work, I rewrote your setTimeout to be around your loop to make the image grow.
setTimeout( function(){
for(i = 0; i < 100; i++) {
grow(i)
}
},400);
Here is the jsfiddle
No, setTimeout fires once, and only once. Additionally, the way you are using setTimeout will lead to unintended results. You are basically saying:
I want to call grow(i) 400 milliseconds from now 100 times.
That means that 400 milliseconds from now, grow(i) will be called 100 times simultaneously. You don't want that, you want to call `grow(i) 100 times, waiting 400 milliseconds between each iteration.
Instead, you should either use setInterval which will wait a duration between each call or have each setTimeout schedule the next timeout after a duration.
Consider:
This will wait 2 seconds and then print 1,2,3,4 all at the same time.
for (let i = 0; i < 5; i++) {
setTimeout(() => console.log(i), 2000);
}
This will print each iteration after a duration:
function iteration(i) {
console.log(i);
if (i > 3) return;
setTimeout(() => iteration(i + 1), 500);
}
iteration(0);
change you javascript to this
var el = document.getElementById("image")
function grow(i) {
console.log(i)
el.style.clipPath = "circle("+ i +"px at 190px 160px)";
}
var i;
for(i = 0; i < 100; i++) {
setTimeout( ((i) => () => grow(i))(i), i*10);
}
and kindly read this once
setTimeout in for-loop does not print consecutive values

How do I delay this code running in JavaScript?

I have written this code to change an image:
change = function(){
for (r=0; r<6; r++){
for (i = 0; i < 6 ; i++) {
setInterval(imgfile(number=i+1), 5000);
}
}
}
imgfile= function(number){
a = 'document.getElementById("imgdiv").src = "images/'+number+'.svg"';
eval(a);
}
The function change() is called when a button is clicked.
When I press the button the image changes straight to 6.svg, when I want it to go through the images 1, 2, 3, 4, 5, 6 and to repeat it 6 times. When I change setInterval to change.setInterval or imgfile.setInterval it doesn't work at all. How do I fix this?
change = function(i=0){
imgfile(i%6+1);//change image
if(i<36) setTimeout(change,5000,i+1);//next image in 5 seconds
}
imgfile= function(number){
document.getElementById("imgdiv").src = "images/"+number+".svg";//no need to use ev(i||a)l
}
Instead of loop/interval mess you can simply start a timeout that restarts itself after changing the image... This code will loop over 6 images with a delay of 5 seconds and that 6 times...
Something like this, perhaps?
var index, imgCount, loopCount, imgTag, countdown;
index = 0;
imgCount = 6;
loopCount = 6;
imgTag = document.getElementById('imgdiv');
countdown = function () {
if (index < imgCount * loopCount) {
imgTag.src = 'images/' + index % imgCount + '.svg';
index = index + 1;
setTimeout(countdown, 5000);
}
};
countdown();
Here we're avoiding the double loop and using modular math (index % imgCount) to get the right file number.
For another question I wrote a nice utility function that has quite a number of uses, but can also handle this scenario very easily. The main issue is that there is no time elapsing between the different delays being set. So you are setting 6 different actions to all happen within 5000ms, and all will occur at the same moment.
Here's my original answer
Here's the utility function for that answer, along with its application to your problem.
function doHeavyTask(params) {
var totalMillisAllotted = params.totalMillisAllotted;
var totalTasks = params.totalTasks;
var tasksPerTick = params.tasksPerTick;
var tasksCompleted = 0;
var totalTicks = Math.ceil(totalTasks / tasksPerTick);
var initialDelay = params.initialDelay;
var interval = null;
if (totalTicks === 0) return;
var doTick = function() {
var totalByEndOfTick = Math.min(tasksCompleted + tasksPerTick, totalTasks);
do {
params.task(tasksCompleted++);
} while(tasksCompleted < totalByEndOfTick);
if (tasksCompleted >= totalTasks) clearInterval(interval);
};
// Tick once immediately, and then as many times as needed using setInterval
if (!initialDelay) doTick();
if (tasksCompleted < totalTicks) interval = setInterval(doTick, totalMillisAllotted / totalTicks);
}
// Do 6 actions over the course of 5000 x 6 milliseconds
doHeavyTask({
totalMillisAllotted: 5000 * 6,
totalTasks: 6,
tasksPerTick: 1,
initialDelay: false, // Controls if the 1st tick should occur immediately
task: function(n) { console.log('Set image to "images/' + (n + 1) + '.svg"'); }
});
You want to do setTimeout().
setTimeout pauses for the millesecond value and then does the code. Where setInterval runs the code every whatever milleseconds.
Yeah, don't do change.setInterval or whatever, it is just setInterval.
An example for you would be this inside the for loop to replace the setInterval function.
setTimeout(imgfile(i+1), 5000);

Can not set timeout in Node.js loop [duplicate]

This question already has answers here:
setTimeout in Node.js loop
(8 answers)
Closed 5 years ago.
Here, i tried to set timeout for every iteration but i could not make it because nature of nodejs. Is there any way to do that?
Thanks in advance
for (var i = 1; i <= 1000; i++) {
setTimeout(function () { console.log('something') }, 3000);
}
It works but it schedules all timeouts at the same time.
If you want to schedule them at 3 sec intervals then use:
for (var i = 1; i <= 1000; i++) {
setTimeout(function () { console.log('something') }, i * 3000);
}
If you want to use i inside of your timeout callbacks, use let instead of var like this:
for (let i = 1; i <= 1000; i++) {
setTimeout(function () { console.log('something', i) }, i * 3000);
}
As you can see with var it would print 1001 for every line:
for (var i = 1; i <= 1000; i++) {
setTimeout(function () { console.log('something', i) }, i * 3000);
}
And by the way, you can simplify it with arrow function syntax:
for (let i = 1; i <= 1000; i++) {
setTimeout(() => console.log('something', i), i * 3000);
}
Another way to do it would be to do something like this - instead of scheduling all 1000 timeouts at the same time, create an interval:
(() => {
let i = 0;
setInterval(() => {
i++;
console.log('something', i);
}, 3000);
})();
The outer closure is to keep the i variable from being visible in the outer scope. OR you can use something like this:
(() => {
let i = 0;
let f = () => {
i++;
console.log('something', i);
setTimeout(f, 3000);
};
setTimeout(f, 3000);
})();
In the last example the function that is invoked as a timeout callback schedules itself every time it finishes.
There are many ways to do it and all have some pros and cons.
For example you shouldn't use setInterval if your callback could potentially run longer than the interval between invocations. It will not be a problem when you use setTimeout and schedule yourself in every callback but on the other hand you may have less precision in the intervals that way. You need to test what works best for you.
for (var i = 1; i <= 10; i++) {
wait('something', i, 10);
}
function wait(msg, i, length){
setTimeout(function ()
{
console.log(msg) ;
}, (i * 3000));
}
try something like this.
Your code actually works but you wait 3 seconds for all which will wait about 1 ms before the next iteration is done runs
I think what you're really looking for is setInterval.
let runMeEveryThreeSeconds = function() {
console.log('hello!')
}
let threeSecondTimer = setInterval(runMeEveryThreeSeconds, 3000)
The timer will run forever, and every three seconds the word 'hello!' will be printed to your console. When you are ready to cancel the timer, you will need to:
clearInterval(threeSecondTimer)

clearInterval stopping setInterval working purely time based

I'm newbie in JS/jQuery, and got quite confused about the usage of stopping a setInterval function from running in x ms (or after running X times), which apparently happens with clearInterval. I know this question was asked similarly before, but couldn't help me.
As you see, it starts with 1000ms delay, and then repeat for 9000ms (or after running 3 times if better??), and then it needs to stop. What's the most ideal way of doing this? I couldn't properly use the clearInterval function. Thanks for the answers!
var elem = $('.someclass');
setTimeout(function() {
setInterval(function() {
elem.fadeOut(1500);
elem.fadeIn(1500);
},3000);
},1000);
To stop the interval you need to keep the handle that setInterval returns:
setTimeout(function() {
var cnt = 0;
var handle = setInterval(function() {
elem.fadeOut(1500);
elem.fadeIn(1500);
if (++cnt == 3) clearInterval(handle);
},3000);
},1000);
Create a counter, and keep a reference to your interval. When the counter hits 3, clear the interval:
var elem = $('.someclass');
setTimeout(function() {
var counter = 0;
var i = setInterval(function() {
elem.fadeOut(1500);
elem.fadeIn(1500);
counter++;
if (counter == 3)
clearInterval(i);
},3000);
},1000);
Given what you are trying to do is quite static, why not simply add delays and forget all the timers.:
var elem = $('.someclass');
elemt.delay(1000).fadeOut(1500).fadeIn(1500).delay(3000).fadeOut(1500).fadeIn(1500).delay(3000).fadeOut(1500).fadeIn(1500).delay(3000);
Or run the above in a small loop if you want to reduce the code size:
elemt.delay(1000);
for (var i = 0; i < 3; i++){
elemt.fadeOut(1500).fadeIn(1500).delay(3000);
}
You just need to clear the interval after three times:
setTimeout(function() {
var times = 0;
var interval = setInterval(function() {
elem.fadeOut(1500);
elem.fadeIn(1500);
if (++times > 3) clearInterval(interval);
},3000);
},1000);

Javascript setTimeout not working in a for-loop

I have to change the source of an image every second. I have a for loop in which a call a function that has a timeout. I read that here, on stackOverflow, but it doesn't work. Can please someone tell me what can I fix to make it work? I've been struggling with this for much more that I'd like to admit. Thanks.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script type="text/javascript">
function changeImage(k) {
setTimeout(function(){
document.getElementById("img").src = k + ".png"; alert(k );}, 1000);
}
function test() {
for (var k = 1; k <= 3; k++) {
changeImage(k);
}
}
</script>
</head>
<body>
<div id="main_img">
<img id="img" src="http://placehold.it/110x110">
</div>
<input type="button" style="width: 200px" onclick="test()" />
</body>
In your code, you set all the timeouts at once. So if you set them all one second from now they all fire one second from now.
You are already passing in the index k so just multiply the time parameter by k.
setTimeout(function(){
document.getElementById("img").src = k + ".png";
alert(k);
}, k * 1000);
// ^ added
The problem is that you are creating instances of a timer milliseconds apart. One second later, they all execute milliseconds apart as well. What you need is to execute them at a set interval apart from each other.
You can use a timer using setInterval, which executes the provided function at a given interval. Don't forget to kill-off the timer though, otherwise it will run forever.
Minor optimizations
You can cache the element in a variable so you won't be hitting the DOM that frequently.
Also, I'd avoid the alert(). If you are debugging, use breakpoints in the debugger. If you really want it to be "alert-like", then use console.log and watch the console.
An advantage of setInterval over a recursive setTimeout is that you will not be spawning multiple timers per iteration, but instead, just one timer.
And here's the proposed solution:
var k = 0;
var image = document.getElementById("img");
var interval = setInterval(function() {
// Increment or clear when finished. Otherwise, you'll leave the timer running.
if(k++ < 3) clearInterval(interval);
image.src = k + ".png";
// Execute block every 1000ms (1 second)
},1000);
Instead of using loop, you can do it like this:
var k = 0;
var int = setInterval(function() {
if (k <= 3) k++;
else { clearInterval(int); }
document.getElementById("img").src = k + ".png";
alert(k);
}, 1000);
My advice is to use console.log() or alert() to help you debug - it'll make it a LOT more obvious what's going on. For instance, if you put a console.log in your test or setTimeout functions, you'd see that all three images were getting added at the same time.
What I'd recommend is to declare your "nextImage" function, then define your setTimeout within that function. That way it'll call itself every second.
Another tip: I assume you want the three images to loop forever, so I added an often used trick with the modulus operator (%) to accomplish this.
Have a look:
Working demo: http://jsfiddle.net/franksvalli/PL63J/2/
(function(){
var numImages = 3, // total count of images
curImage = 1, // start with image 1
$image = document.getElementById("img"),
imageBase = "http://placehold.it/110x11";
function nextImage() {
$image.src = imageBase + curImage;
// increment by one, but loop back to 1 if the count exceeds numImages
curImage = (curImage % numImages) + 1;
// execute nextImage again in roughly 1 second
window.setTimeout(nextImage, 1000);
}
// initializer. Hook this into a click event if you need to
nextImage();
})();
As other folks have said, you probably want to use setInterval, which you can do with some tweaks:
(function(){
var numImages = 3, // total count of images
curImage = 1, // start with image 1
$image = document.getElementById("img"),
imageBase = "http://placehold.it/110x11";
function nextImage() {
$image.src = imageBase + curImage;
// increment by one, but loop back to 1 if the count exceeds numImages
curImage = (curImage % numImages) + 1;
}
// initializer. Hook this into a click event if you need to
nextImage(); // call function immediately without delay
window.setInterval(nextImage, 1000);
})();
The problem
setTimeout doesn't stop the program execution but only sets up an event for a callback in 1 second. What that means is that if you setup three setTimeout's inside your for loop, they will execute simultaneously after 1 second.
A solution
Instead of using a for loop, you can use a delayed recursion.
function changeImage(imageIndex) {
document.getElementById("img").src = imageIndex + ".png";
alert(imageIndex);
}
function myLoop( imageIndex ) {
if( imageIndex >= 3 ) return;
changeImage( imageIndex );
setTimeut( function() { myLoop(imageIndex + 1) }, 1000 );
}
setTimeut( function() { myLoop(0) }, 1000 );
Another solution using setInterval
var interval = null;
var imageIndex = 0;
function changeImage() {
document.getElementById("img").src = imageIndex + ".png";
alert(imageIndex);
imageIndex++;
if( imageIndex === 3 ) clearInterval( interval );
}
interval = setInterval( changeImage , 1000);
Using different delays
function changeImage(imageIndex) {
document.getElementById("img").src = imageIndex + ".png";
alert(imageIndex);
}
for( var i=0; i < 3; i++) {
setTimeout( changeImage.bind(window, i), i * 1000 );
}
A groovy one liner( please don't use this, ever! )
(function f(i) { setTimeout( changeImage(i) || f.bind(window, i = (i++)%3), 1000); })(0)
WHY IT DOESN'T WORK?
Because Javascript always passes variables by reference. When your code is waiting on the queue, the variables have already changed.
MY SOLUTION:
Create an array and push whatever codes you want to execute in order of appearance (Place the real value of the variables directly) e.g.:
var launcher = [];
launcher.push('alert("First line of code with variable '+ x +'")');
launcher.push('alert("Second line of code with variable '+ y +'")');
launcher.push('alert("Third line of code with variable '+ z +'")');
Use setInterval instead of setTimeout to execute the codes (You can even change the delay period dynamically) e.g.
var loop = launcher.length;
var i = 0;
var i1 = setInterval(function(){
eval(launcher[count]);
count++;
if(i >= loop) {
clearInterval(i1);
}
}, 20);

Categories

Resources