How to set time delay in javascript - javascript

I have this a piece of js in my website to switch images but need a delay when you click the image a second time. The delay should be 1000ms. So you would click the img.jpg then the img_onclick.jpg would appear. You would then click the img_onclick.jpg image there should then be a delay of 1000ms before the img.jpg is shown again.
Here is the code:
jQuery(document).ready(function($) {
$(".toggle-container").hide();
$(".trigger").toggle(function () {
$(this).addClass("active");
$(".trigger").find('img').prop('src', 'http://localhost:8888/images/img_onclick.jpg');
}, function () {
$(this).removeClass("active");
$(".trigger").find('img').prop('src', 'http://localhost:8888/images/img.jpg');
});
$(".trigger").click(function () {
$(this).next(".toggle-container").slideToggle();
});
});

Use setTimeout():
var delayInMilliseconds = 1000; //1 second
setTimeout(function() {
//your code to be executed after 1 second
}, delayInMilliseconds);
If you want to do it without setTimeout: Refer to this question.

setTimeout(function(){
}, 500);
Place your code inside of the { }
500 = 0.5 seconds
2200 = 2.2 seconds
etc.

ES-6 Solution
Below is a sample code which uses aync/await to have an actual delay.
There are many constraints and this may not be useful, but just posting here for fun..
const delay = (delayInms) => {
return new Promise(resolve => setTimeout(resolve, delayInms));
}
const sample = async () => {
console.log('a');
console.log('waiting...')
let delayres = await delay(3000);
console.log('b');
}
sample();

you can use the promise
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
then use this method
console.log("Hello");
sleep(2000).then(() => { console.log("World!"); });
or
console.log("Hello");
await sleep(2000);
console.log("World!");

There are two (mostly used) types of timer function in javascript setTimeout and setInterval (other)
Both these methods have same signature. They take a call back function and delay time as parameter.
setTimeout executes only once after the delay whereas setInterval keeps on calling the callback function after every delay milisecs.
both these methods returns an integer identifier that can be used to clear them before the timer expires.
clearTimeout and clearInterval both these methods take an integer identifier returned from above functions setTimeout and setInterval
Example:
setTimeout
alert("before setTimeout");
setTimeout(function(){
alert("I am setTimeout");
},1000); //delay is in milliseconds
alert("after setTimeout");
If you run the the above code you will see that it alerts before setTimeout and then after setTimeout finally it alerts I am setTimeout after 1sec (1000ms)
What you can notice from the example is that the setTimeout(...) is asynchronous which means it doesn't wait for the timer to get elapsed before going to next statement i.e alert("after setTimeout");
Example:
setInterval
alert("before setInterval"); //called first
var tid = setInterval(function(){
//called 5 times each time after one second
//before getting cleared by below timeout.
alert("I am setInterval");
},1000); //delay is in milliseconds
alert("after setInterval"); //called second
setTimeout(function(){
clearInterval(tid); //clear above interval after 5 seconds
},5000);
If you run the the above code you will see that it alerts before setInterval and then after setInterval finally it alerts I am setInterval 5 times after 1sec (1000ms) because the setTimeout clear the timer after 5 seconds or else every 1 second you will get alert I am setInterval Infinitely.
How browser internally does that?
I will explain in brief.
To understand that you have to know about event queue in javascript. There is a event queue implemented in browser. Whenever an event get triggered in js, all of these events (like click etc.. ) are added to this queue. When your browser has nothing to execute it takes an event from queue and executes them one by one.
Now, when you call setTimeout or setInterval your callback get registered to an timer in browser and it gets added to the event queue after the given time expires and eventually javascript takes the event from the queue and executes it.
This happens so, because javascript engine are single threaded and they can execute only one thing at a time. So, they cannot execute other javascript and keep track of your timer. That is why these timers are registered with browser (browser are not single threaded) and it can keep track of timer and add an event in the queue after the timer expires.
same happens for setInterval only in this case the event is added to the queue again and again after the specified interval until it gets cleared or browser page refreshed.
Note
The delay parameter you pass to these functions is the minimum delay
time to execute the callback. This is because after the timer expires
the browser adds the event to the queue to be executed by the
javascript engine but the execution of the callback depends upon your
events position in the queue and as the engine is single threaded it
will execute all the events in the queue one by one.
Hence, your callback may sometime take more than the specified delay time to be called specially when your other code blocks the thread and not giving it time to process what's there in the queue.
And as I mentioned javascript is single thread. So, if you block the thread for long.
Like this code
while(true) { //infinite loop
}
Your user may get a message saying page not responding.

For sync calls you can use the method below:
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds){
break;
}
}
}

If you need refresh, this is another posibility:
setTimeout(function () {
$("#jsSegurosProductos").jsGrid("refresh");
}, 1000);

I'll give my input because it helps me understand what im doing.
To make an auto scrolling slide show that has a 3 second wait I did the following:
var isPlaying = true;
function autoPlay(playing){
var delayTime = 3000;
var timeIncrement = 3000;
if(playing){
for(var i=0; i<6; i++){//I have 6 images
setTimeout(nextImage, delayTime);
delayTime += timeIncrement;
}
isPlaying = false;
}else{
alert("auto play off");
}
}
autoPlay(isPlaying);
Remember that when executing setTimeout() like this; it will execute all time out functions as if they where executed at the same time assuming that in setTimeout(nextImage, delayTime);delay time is a static 3000 milliseconds.
What I did to account for this was add an extra 3000 milli/s after each for loop incrementation via delayTime += timeIncrement;.
For those who care here is what my nextImage() looks like:
function nextImage(){
if(currentImg === 1){//change to img 2
for(var i=0; i<6; i++){
images[i].style.zIndex = "0";
}
images[1].style.zIndex = "1";
imgNumber.innerHTML = imageNumber_Text[1];
imgDescription.innerHTML = imgDescText[1];
currentImg = 2;
}
else if(currentImg === 2){//change to img 3
for(var i=0; i<6; i++){
images[i].style.zIndex = "0";
}
images[2].style.zIndex = "1";
imgNumber.innerHTML = imageNumber_Text[2];
imgDescription.innerHTML = imgDescText[2];
currentImg = 3;
}
else if(currentImg === 3){//change to img 4
for(var i=0; i<6; i++){
images[i].style.zIndex = "0";
}
images[3].style.zIndex = "1";
imgNumber.innerHTML = imageNumber_Text[3];
imgDescription.innerHTML = imgDescText[3];
currentImg = 4;
}
else if(currentImg === 4){//change to img 5
for(var i=0; i<6; i++){
images[i].style.zIndex = "0";
}
images[4].style.zIndex = "1";
imgNumber.innerHTML = imageNumber_Text[4];
imgDescription.innerHTML = imgDescText[4];
currentImg = 5;
}
else if(currentImg === 5){//change to img 6
for(var i=0; i<6; i++){
images[i].style.zIndex = "0";
}
images[5].style.zIndex = "1";
imgNumber.innerHTML = imageNumber_Text[5];
imgDescription.innerHTML = imgDescText[5];
currentImg = 6;
}
else if(currentImg === 6){//change to img 1
for(var i=0; i<6; i++){
images[i].style.zIndex = "0";
}
images[0].style.zIndex = "1";
imgNumber.innerHTML = imageNumber_Text[0];
imgDescription.innerHTML = imgDescText[0];
currentImg = 1;
}
}

I'm not an expert in JS domain but I've found a workaround for this problem using setTimeout() and a recursive function as follows:
i=0; //you should set i as a global variable
function recFunc() {
i++;
if (i == 1) {
//do job1
} else if (i == 2) {
//do job2
} else if (i == 3) {
//do job3
}
if (i < 3) { //we have 3 distinct jobs. so the condition is (j < 3)
setTimeout(function () {
recFunc();
}, 2000); //replace 2000 with desired delay
}
}
//
//
//
recfunc(); //start the process

const delay = (delayInms) => new Promise(resolve => setTimeout(resolve, delayInms));
await delay(100)

Related

For Loop SetTimeout Works Only 1 Time

I have a button with click function below. It has 3 nested for loop, and 1 setTimeout function.
The below loops are looping 5 times. I want below code to work(5x5) total 25 seconds of execution time, and each 5 seconds console output should be "Waited" printed.
However below code works only 5 seconds, and immediately prints "5 hello". Without changing my for loop structure, how can I make it work as I want?
jQuery("#btn_trendyolStocksSYNC").click(function() {
for(var product in all){
var colors = all[product];
for(var singleColor in colors[0]){
var size = colors[0][singleColor];
for(var index in size){
var singleSize = size[index];
setTimeout(function (){
console.log('Waited');
}, 5000);
}
}
}
});
Edit: I don't use the for loop with indexes, so solutions for number indexed for loops are not working for me.
You could try by adding await and a Promise:
jQuery("#btn_trendyolStocksSYNC").click(async function() {
for(var product in all){
var colors = all[product];
for(var singleColor in colors[0]){
var size = colors[0][singleColor];
for(var index in size){
var singleSize = size[index];
await new Promise(resolve => setTimeout(function (){
console.log('Waited');
resolve();
}, 5000));
}
}
}
});
What this does is simply tell your loop to stop and only continue once the Promise object calls its resolve parameter function. That way your delay should simply happen before the next iteration. This is the important code:
await new Promise(resolve => setTimeout(function (){
console.log('Waited');
resolve();
}, 5000));
It simply creates a Promise that we will resolve once the timeout has let 5000 milliseconds pass. Then we tell our loop to simply await that completion before continuing to the next item.
Note You also need to add async to your handler function, so javascript knows that this function can wait and take as long as it needs to.
The setTimeout(); function is asynchronous, meaning that your script will not wait for it to finish before moving on. That's why it has a callback.
Try something like this: (not the best method)
//delayed loop
var i = 1;
function loop() {
//wait 5 secs
setTimeout(function() {
console.log(i);
if(i>5) {
//cancel
return;
}
loop();
i++;
return;
}, 1000);
if(i>5) {
//cancel function
return;
}
}
//do the loop
loop();
Like what somethinghere said, you could put the setTimeout in the if statement.
Of course to do something after the loop ends you need a callback function.
you can use setInterval and clearInterval.
var n=0;
var a = setInterval(()=>{
console.log("Waited");
n++; if(n==5){clearInterval(a);}
},5000);

Javascript while setTimeout [duplicate]

This question already has answers here:
How do I add a delay in a JavaScript loop?
(32 answers)
Closed 6 years ago.
I want to make a GreaseMonkey script. I want to have a setTimeout at the end of my while, but I don't know how to do that.
run();
function run(){
var klovas = document.getElementById("light").innerHTML;
var btn = document.getElementsByClassName("farm_icon farm_icon_a");
if(klovas < 6){
alert("Kevés egység van");
} else {
var i = 0;
while (i < btn.length){
if(typeof btn[i] != "undefined"){
btn[i].click();
}
i++;
setTimeout("run()", 3000);
}
}
}
With this code, the problem is that the setTimeout is not working and doesn't wait 3 seconds like it is supposed to.
I tried other ways, but nothing has worked.
EDIT
function run(){
var klovas = document.getElementById("light").innerHTML;
var btn = document.getElementsByClassName("farm_icon farm_icon_a");
if(klovas < 2){
alert("Kevés egység van");
} else {
var i = 0;
while (i < btn.length){
if(typeof btn[i] != "undefined"){
btn[i].click();
}
i++;
}
}
}
setInterval(run, 6000);
I tryed this. Its runing every 6 sec, but i get error in website, that i cand click more than 5 times in a sec. So waiting 6secound when i open the page, and after click, and i get error. Its not jet working. :(
If you wanted it to only trigger once:
function run(){
var data = [1,2,3];
var i = 0;
while (i < data.length) {
console.log(data[i]);
i++;
}
}
setTimeout(run, 3000);
The way you wrote it now, it would repeat every 3 seconds.
function run(){
var data = [1,2,3];
var i = 0;
while (i < data.length) {
console.log(data[i]);
i++;
}
setTimeout(run, 3000);
}
run();
But setInterval would accomplish the same results.
function run(){
var data = [1,2,3];
var i = 0;
while (i < data.length) {
console.log(data[i]);
i++;
}
}
setInterval(run, 3000);
EDIT
User wanted to see what would happen if you call setInterval from inside the callback function. Note that the number of intervals grows exponentially every 3 seconds.
setInterval causes the function to run every 3 seconds, while setTimeout causes the function to run once in 3 seconds.
var numberOfIntervals = 0;
function run(){
setInterval(run, 3000);
numberOfIntervals++;
console.log(numberOfIntervals);
}
run();
There are a few problems here.
Firstly, while setTimeout can accept a function as its first argument, you would want to pass the function as an argument, not execute the function, so you should replace "run()" with run.
Secondly, I'm not exactly sure why you're recursing -- why is setTimeout inside run()? Instead of putting it inside your run function, try putting it at the bottom, and deleting the run() call at the top. As far as I can tell, there's no reason that this code needs to recurse at alll.

setInterval within a for-loop not working

What I want is an infinite loop that alerts 1, 2, 3, 1, 2, 3, ... with an interval of 2000 milliseconds. But it's not working. The console's not showing any error though. What's the problem here?
for (i = 1; i <= 3; i++) {
setInterval(function() {
alert(i);
}, 2000);
if (i == 3) {
i = 0;
}
}
This will do:
var i = 0;
setInterval(function () {
i += 1;
if (i == 4) {
i = 1;
}
alert(i);
}, 2000);
I've checked it chrome too.
It outputs 1,2,3,1,2,3... as you have requested.
you can not setInterval() inside a for loop because it will create multiple timer instance.
The setInterval() method calls a function or evaluates an expression at specified intervals (in milliseconds).
The setInterval() method will continue calling the function until clearInterval() is called, or the window is closed.
The ID value returned by setInterval() is used as the parameter for the clearInterval() method.
Tip: To execute a function only once, after a specified number of milliseconds, use the setTimeout() method.
var i = 0
function test() {
i = i % 3;
++i;
alert(i);
};
setInterval('test()', 2000);
You would not need a loop for this, an interval already goes on infinitley. Try this instead:
var i = 1;
setInterval(function() {
alert(i);
i++;
if(i > 3) {
i = 1;
}
}, 2000);
The reason why this is not working is because you enter the infinite loop in a blocking state, meaning that the interval is never entered as the browser is busy looping. Imagine the browser can only do one thing at a time, as in a single thread, so the loop is it, and cannot do anything else until it's done, and in your case it never is, therefore the interval is waiting for it's turn, which it never gets.
You could make it none blocking like this:
function recursion () {
for (var i = 1; i < 4; i++) {
var num = i;
setInterval(function() {
console.log(String(this));
}.bind(num), 2000);
}
recursion ();
}
recursion ();
my best suggestion is . use event monogramming righterthen loop ,
first make a function then after completing of setInterval call to next function and so on.. that's how u can solve this p

Why isn't clearInterval working in this code?

There is a function which sets an interval using setInterval(), but even after calling clearInterval(), I can see in the console that the else condition is still running. How can I clear that interval properly?
function increase(old, step, neu) {
var i = 0;
var delay2;
function countUp() {
if (i < 5) {
old += step;
// console.log("increase")
$("#total-price-value").text(old + " dollors");
$("#total-price-value").digits();
i++;
delay2 = setInterval(countUp, 80);
} else {
clearInterval(delay2);
console.log(delay2);
}
}
countUp();
}​
It looks like you're a little confused about the difference between timeouts and intervals. Timeouts fire only once; intervals fire many times. If you're using an interval, you probably only want to set it once (you're setting it every time). If you're using a timeout, you probably want to set it every time (like you're doing).
In order to fix the problem, you'll either want to switch to timeouts (probably the easiest; just a search/replace) or only set the interval once.
For example, here is how one might use setTimeout to count up to five:
var count = 0;
function timeoutFired() {
count++;
if(count < 5) {
setTimeout(timeoutFired, 1000);
}
}
setTimeout(timeoutFired, 1000);
Using timeouts, we don't need to clear to stop it from counting; simply not setting a timeout will prevent it from running again.
Here is how one might use setInterval:
var count = 0;
function intervalFired() {
count++;
if(count >= 5) {
clearInterval(interval);
}
}
var interval = setInterval(intervalFired, 1000);
If you want some code running periodically using intervals to stop, you must call clearInterval. Note that we only call setInterval once, versus setTimeout every time we didn't want it to continue.
Apparently, you have mistaken setInterval for setTimeout. setInterval runs the enclosed function every n milliseconds while setTimeout executes only once after n milliseconds.
I suppose you wanted to "tick until 5" so here's a sample:
function increase(old, step, neu) {
var i = 0;
interval = setInterval(function() {
if (i < 5) {
//do something at this "tick"
console.log(i);
i++;
} else {
//else, stop
clearInterval(interval);
}
},80);
}
increase();

How can I resume setInterval after clearInterval has been called in javascript?

I have this code which works ok but I would like to stop polling and clearInterval if the user is inactive (no mouse move) after say 5 iterations rather than be in a continuous loop.
var i, active = new Date, iter = 1;
$(window).on('mousemove', function(e){
active = new Date;
});
i = setInterval(function(){
if(new Date().getTime() - active.getTime() < 1000){
console.log("sending active event to server.....");
iter = 1;
else{
iter++;
if(iter >= 5){
clearInterval(i);
}
}
}, 2000);
right now it checks every two seconds in this example. I would like to check the active date say 5 times and if its expired 5 iterations in a row, call clearInterval(i)... so something inside the mousemove callback should reinitialize the setInterval only if it's currently not running. How can I accomplish this? Thanks for any tips and samples. I'd like to keep using an anonymous function if possible.
Seperate the Interval function
function intFunc(){
if(new Date().getTime() - active.getTime() < 1000){
console.log("sending active event to server.....");
iter = 1;
else{
iter++;
if(iter >= 5){
clearInterval(i);
}
}
};
Now, call them on the two places you need
var i;
$(window).on('mousemove', function(e){
active = new Date;
i = setInterval(intFunc, 2000);
});
i = setInterval(intFunc, 2000);
One simple way would just be to remove the clearInterval call, and instead only poll the server when iter < 5.
But that's still a little wasteful, as the handler is still being called when it has nothing to do, which is bad when you want your laptop/phone to stay in powersaving mode. So what I'd do is basically what you have, but after calling clearInterval, set up a one-time mousemove handler that restarts polling.
I'm not seeing a way to do that without naming a function (I'm presuming you don't want to get into Y-combinators and the like), but you can hide its name – and the others – from the outside world by using an anonymous function around the whole thing:
(function () {
var i, active = new Date, iter = 1;
$(window).on('mousemove', function(e) {
active = new Date;
});
function startPolling() {
i = setInterval(function() {
if (new Date().getTime() - active.getTime() < 1000) {
console.log("sending active event to server.....");
iter = 1;
}
else{
iter++;
if (iter >= 5) {
clearInterval(i);
$(window).one('mousemove', function () {
startPolling();
});
}
}
}, 2000);
}
startPolling();
})();

Categories