I'm trying to write a simple loop in JS (or JQuery) that updates an image every five seconds, for a total of 15 seconds (so three loops), and then quits.
It should go like this:
Wait five seconds
Execute
Wait five seconds
Execute
Wait five seconds
Execute
Quit
But setTimeout only seems to work once.
As a test, I've tried:
function doSetTimeout(i) {
setTimeout(function() { alert(i); }, 5000);
}
for (var i = 1; i <= 5; ++i)
doSetTimeout(i);
Does not work: http://jsfiddle.net/ubruksco/
I've also tried:
for(var i = 1; i <= 5; i++) {
(function(index) {
setTimeout(function() { alert(index); }, 5000);
})(i);
}
Does not work: http://jsfiddle.net/Ljr9fq88/
var time = 1;
var interval = setInterval(function() {
if (time <= 3) {
alert(time);
time++;
}
else {
clearInterval(interval);
}
}, 5000);
you can simply create an interval and kill it after the 3rd time
Your first example is nearly there. You just need to multiply the time delay by the loop index to get the right delay.
function doSetTimeout(i) {
setTimeout(function() { alert(i); }, 5000*i);
}
for (var i = 1; i <= 3; ++i)
doSetTimeout(i);
http://jsfiddle.net/ubruksco/3/
The reason is that your settimeout ends all at the same time (after 5 seconds) because your timeout code is based on 5 seconds
for(var i = 1; i <= 5; i++) {
(function(index) {
setTimeout(function() { alert(index); }, 5000);
})(i);
}
What you want to do is change the timeout time based on your index (hence will have different start times.
for(var i = 0; i < 3; i++) {
(function(index) {
setTimeout(function() { alert(index); }, index*5000);
})(i);
}
(Also needs 3 iterations, so edited out the loop for you)
You want setInterval() instead
setInterval(function(){ alert("Do Something"); }, 3000);
Make it easy! You do not need loop, you just need three executions.
setTimeout(function() { alert(1); }, 5000);
setTimeout(function() { alert(2); }, 10000);
setTimeout(function() { alert(3); }, 15000);
But, if you really want a loop:
function doSetTimeout(i) {
setTimeout(function() { alert(i); }, i*5000);
}
for (var i = 1; i <= 3; ++i)
doSetTimeout(i);
Assuming your are using jQuery (to manipulate the DOM),
you can try this:
['img1.jpg', 'img2.jpg', 'img3.jpg'].forEach(function(imgPath, index) {
// the callback will be executed in 5seconds * (index + 1)
setTimeout(function() {
// change image source
$('img#myImage').attr('src', imgPath);
}, 5000 * (index + 1));
});
With setTimeout:
function doSetTimeout(i) {
if(i >= 3) return;
alert(i);
setTimeout((function () {
return function () {
doSetTimeout(i);
};
})(i + 1), 5000);
}
doSetTimeout(0);
But you can also use setInterval, maybe more appropriate.
You can use setInterval instead and track how much times you have executed function. Than just use clearInterval() to stop execution.
var i = 1;
var interval = setInterval(function() {
execute();
}, 5000);
$(document).ready(function() {
execute();
});
function execute() {
$("#output").append("set<br/>");
if (i == 3) {
clearInterval(interval);
}
i++;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='output'></div>
If you want to first wait 5 secs, don't call execute() on domready.
Related
If I use setTimeout in a loop so only after the loop ends it executes all the operation in the same time.
I tried to put setTimeout in a separate function, as suggested by many articles, but it does not help.
The code is very simple:
function foo(i)
{
setTimeout( function() {console.log(i);}, 2000);
}
for (let i=0; i<5; i++)
{
foo(i);
}
It prints
0
1
2
3
4
in one shot
It's because the proccess registry the 5 setTimeout at almost the same time.
Try with the different timeout time like this:
function foo(i)
{
setTimeout( function() {console.log(i);}, 1000 * i);
}
for (let i=0; i<5; i++)
{
foo(i);
}
you could also do it with a generator. a generator can pause midway through a function
https://www.javascripttutorial.net/es6/javascript-generators/
function* generator() {
let index = 1;
while (index <= 5) {
yield index++;
}
}
let f = generator();
var interval = window.setInterval(function(){
const obj = f.next();
if (obj.done){
clearInterval(interval);
} else {
console.log(obj.value)
}
}, 1000);
I'm trying to create an image slider for a website, I want to learn why my array won't go back to zero after finishing the first iteration and keep on iterating. I want the slider to iterate on and on automatically.
function run() {
for (let i = 0; i < imgArray.length; i++) {
(function(e) {
setTimeout(function() {
if (i == imgArray.length) {
i = 0;
}
imgContainer.style.background = imgArray[i];
}, 3000 * e);
})(i);
};
imgContainer.style.height = '100vh';
}
The condition i == imgArray.length inside the loop is never true, since the loop runs until i < imgArray.length. You could use <= instead as Ali Abug Hijleh suggested, but I think it would be easier to maintain if you explicitly show the loop should run forever with while (true) and use the % operator to get the right index:
function run() {
let i = 0;
while (true) {
(function(e) {
setTimeout(function() {
imgContainer.style.background = imgArray[i % imgArray.length];
}, 3000 * e);
})(i);
};
imgContainer.style.height = '100vh';
++i;
}
i will never reach the imgArray.length because the loop only works when i is less than imgArray.length (since you use i < imgArray.length as the condition)
Try if (i == imgArray.length -1) { ... } instead.
That's because your for loop ends before you reset it to zero because you reset it to zero inside a setTimeout
I've created a simple counter using javascript but there is a problem Field "display" starts from 1, but it should start from 100 and goes low. The console logs shows values correctly from 100 to 1.
I have to use loops to do this tasks, so please not replace it using recursion :) Also the timeout is for sure does not equal to 100ms, it's more
function wyswietlLiczbe(j) {
setTimeout(function() {
document.getElementById("display").innerHTML = j;
}, 100);
}
for (var i= 100; i > 0; i--){
console.log(i)
wyswietlLiczbe(i);
}
<p id="display"></p>
Since the loop executes immediately, you need to wait an increasing amount of time for each number. This will queue up the innerHTML modifications.
As it is now, after a 100ms wait all 100 wyswietlLiczbe are executed in rapid succession.
function wyswietlLiczbe(j, waitTime) {
setTimeout(function() {
document.getElementById("display").innerHTML = j;
}, waitTime);
}
for (var i= 100; i > 0; i--){
console.log(i)
wyswietlLiczbe(i, (101 - i) * 100);
}
<p id="display"></p>
Build the conditional into the function which will execute after the timeout.
var elmD = document.getElementById("display");
function wyswietlLiczbe(j) {
setTimeout(function() {
elmD.innerHTML = j;
j--;
if(0 <= j ) {
wyswietlLiczbe(j)
}
}, 100);
}
wyswietlLiczbe(100);
I don't know exactly what you want but I think this is what you're looking for.
function wyswietlLiczbe(j) {
if (j >= 0) {
setTimeout(function() {
document.getElementById("display").innerHTML = j;
j--;
wyswietlLiczbe(j);
}, 100);
}
}
wyswietlLiczbe(100);
<p id="display"></p>
you can use setInterval instead
function wyswietlLiczbe(j) {
x = setInterval(function() {
if(j==0) clearInterval(x);
document.getElementById("display").innerHTML = j--;
}, 100);
}
wyswietlLiczbe(100);
I have this script:
var array = [];
array[0] = 'http://facebook.com/';
array[1] = 'http://instagram.com/';
array[2] = 'http://twitter.com';
$(document).ready(function()
{
for(i=0; i<= 2; i++)
{
$('#ifr').attr('src', array[i]);
// sleep here for 0,5 second
}
});
And how I can stop this loop for 0.5 second?
You can use setTimeout for this purpose,
for(i=0; i<=2; i++) {
setTimeout(function(i) {
$('#ifr').attr('src', array[i]);
},500 * i,i);
//1000 ms is 1 sec, here I have give 0.5 seconds as a delay.
}
There is no need to create scope per iteration for handling the closure problem. You can use the third parameter of setTimout to set the argument of callBack function.
(function rec(i){
setTimeout(function(){
$('#ifr').attr('src', array[i]);
if(i <= 2) rec(i+1);
}, 5000);
})(0);
EDIT: added if(i <= 2) so that it doesn't recurse forever.. this will stop it after 2 iterations..
I want to find elements with javascript with delay. In first step I made this and it works.
function mytag() {
var elements = document.getElementsByTagName('div');
for (var i=0, im=elements.length; im>i; i++) {
if (elements[i].className ==='hi'){
alert('found');
}}
}
In the second step, I made some changes to code to put delay between iteration. I followed this link but cannot make it to work . Whats wrong?
function mytag() {
var elements = document.getElementsByTagName('div');
for (var i=0, im=elements.length; im>i; i++) {
(function(i){
setTimeout(function(){
if (elements[i].className ==='hi'){
alert('found!');
}
}, 3000 * i);
}(i));
}
}
Here's an example of how you could add asynchronousity into your lookup function:
function findElements() {
var elements = document.getElementsByTagName('div');
var index = 0;
var findNext = function() {
var element = elements[index];
index++;
if (element.className === 'hi'){
// Item found
console.log('found:'+element);
}
if (index < elements.length) {
setTimeout(findNext, 100);
}
};
findNext();
}
findElements();
http://jsbin.com/zeseguribo/1/edit?html,js,console
function sleep(milliseconds) {
var start = new Date().getTime();
while (1) {
if ((new Date().getTime() - start) > milliseconds) {
break;
}
}
} // sleep end
then call sleep(3000) in your loop.
Edit: This is a blocking way of delay. For async, non-blocking delay, you may use a recursive function.