How to set a variable after x seconds? - javascript

I'm basically trying to accomplish the following. I want it so 5 seconds after the page loads, it'll set the variable to true.
Once true, it'll proceed to give the alert "true".. for now. If someone tries to click the button before 5 seconds, it'll give the alert false.

You've got the right idea, but you have a minor issue with variable scope. To reduce headaches, it's really best to get away from using the string eval option on setTimeout (which is shown in tutorials all around the web, I know) and use an anonymous function:
var link;
function loading(){
setTimeout(function(){
link = true;
}, 5000);
}
This way, you'll know exactly where link is declared and the scope is crystal clear.

Try this:
setTimeout(function() { window.link = true; }, 5000);
This will set the global variable "link" to true after 5 seconds, which will satisfy your if statement.
Edit
This may be a bit complicated if you're a beginner, but a better way to accomplish this is to use function-scope rather than global scope.
In your case, declare the timer function like this:
var timer = (function () {
var link = false;
setTimeout(function() { link = true; }, 5000);
return function() {
alert(link);
};
}());
This way, the anonymous function returns another function which becomes timer(), but this way timer has access to its "private" link variable. For more information, check out Mozilla's article on JavaScript variable scope

Simple one-liner timeout:
setTimeout(() => alert("Time is up!"), 1000);
You can obviously execute any code within:
let seconds = 5;
let timer = setInterval(() => console.log(`${seconds--} seconds left`), 1000);
setTimeout(() => {
clearInterval(timer);
console.log('💥')
}, 5999);

Related

Setting variables using timer in JS

trying to figure out how to do this and I'm not too sure. I'm trying to update local GPS coordinates every 3 seconds using setTimeout and it's not working properly. I'm very new to js so any help is appreciated. This is what I have so far-
In my main JS file, I have this...
var lat_in={};
var long_in={};
var alt_in={};
$.getScript("test_points.js", function(){
console.log("TP script go");
});
$("#Initiate").click(function() {
if (coordinate=="GPS")
{
console.log("GPS go");
lat_out = lat_in;
long_out = long_in;
alt_out = alt_in;
console.log(lat_out, long_out, alt_out)
}
)}
I'm calling the lat/long/alt from another js document (test_points.js), where the setTimeout is...
setTimeout(function(){
var lat_in=5;
var long_in=5;
var alt_in=-5;
}, 3000);
I have a bunch of setTimeouts one after another, and what I'm trying to do is update the variables every 3 seconds and run them through the if statement again.
Am I even close to doing this properly? Thanks in advance
You have declared those variables with a "var" keyword which makes them local to the function passed to the timeout function. Please remove var and try again.
EDIT :
As other have pointed out, you should use interval instead of timeout and once the changes are reflected, then only you should try accessing them.
JavaScript has two kind of timers, one provides a timeout (delayed execution of a piece of code) called window.setTimeout (because setTimeout is a method of the window object) and a timer that runs a piece of code after a certain interval called window.setInterval.
Watch how both work
setTimeout(function(){
document.getElementById("showcase").innerHTML += "setTimeout fired only once after 3 seconds. <br />"}, 3000);
setInterval(function(){
document.getElementById("showcase").innerHTML += "setInterval fired every after 5 seconds. <br />"}, 5000);
//not part of the solution, just to demonstrate.
setInterval(function(){
document.getElementById("timer").textContent = 1 + parseInt(document.getElementById("timer").textContent);
}, 1000)
#showcase {
padding: 4px;
border: 1px solid grey;
background-color: #f3f3f3;
}
<span id="timer">0</span> seconds <br />
<div id="showcase"></div>
To let a timer run multiple times use setInterval.
On your case
setTimeout(function(){
var lat_in=5;
var long_in=5;
var alt_in=-5;
}, 3000);
When you replace setTimeout to setInterval it still won't work. As others commented, you are declaring the lat_in etc. inside the scope of the function. This means that the variables inside that function are only accessibele inside the function bound to the interval. The keyword is var. It tells the parser to "bind" the variables to the scope of the function. Leave the var and your timer function will overwrite the global variables declared outside the function. The sample below should be fine.
setInterval(function(){
lat_in=5;
long_in=5;
alt_in=-5;
}, 3000);
Also when you first declared the variables they are declared as an empty object.
var lat_in={};
var long_in={};
var alt_in={};
using {} is the same as doing lat_in = new Object(). However in your function you overwrite them with integers. Maybe this isn't meant to be. Check the documentation on your GPS coding to what input it needs.
While we are at it:
you can stop timers too with window.clearTimeout and window.clearInterval. Each referring to its own function of course.
To do this, you need to store the timer into a variable:
timer = window.SetInterval(function(){ ... }, 3000); //always in milliseconds.
clearInterval(timer); // this line will now clear the timer.
Also a smart person could remark: "I can let setTimeout behave like an interval."
window.setTimeout(myTimerFunction, 3000);
function myTimerFunction(){
//do stuff here
window.setTimeout(myTimerFunction, 3000); //call itself again in three seconds.
}
Since setTime out is asynchronous you should not start expressions like lat_out = lat_in; before initialising.
And also you are declaring the variables using Var which makes them local.so remove var.
Simply use setInterval function to call a function after an interval continuesly
$("#Initiate").click(function() {
var intervalCall = window.setInterval(myCallback, 3000);
)}
function myCallback(){
if (coordinate=="GPS")
{
console.log("GPS go");
lat_out = lat_in;
long_out = long_in;
alt_out = alt_in;
console.log(lat_out, long_out, alt_out)
}
}
For more information about setInterval, you can read here

jQuery function loop don't stop after checkbox unchecked

I have a checkbox, which starts a loop of a function called "next". So far that work's correctly. Unckecked box should stop the function loop. That doesn't work. I found in the stackoverflow-forum, that it is necessary to declare a variable of the Interval-ID outside the if-else-statement. No success. Any ideas?
This is the code:
$('input[type="checkbox"]').click(function(){
var intervalID = 0;
if($(this).is(":checked")){
var intervalID = setInterval(next, 400);
}
else if($(this).is(":not(:checked)")){
clearInterval(intervalID);
}
}
);
Regards
"I found in the stackoverflow-forum, that it is necessary to declare a variable of the Interval-ID outside the if-else-statement"
There's a lot more to scopes than that. In your case, when you initialise a variable inside the function, it is only available inside that function. I would highly recommend reading up on scopes, there's a lot of good information out there that doesn't need to be repeated here. For example: http://www.smashingmagazine.com/2009/08/01/what-you-need-to-know-about-javascript-scope/
You really need to run through your code to understand what's happening. Look at the code and think about it. Every time a checkbox is clicked, you are setting intervalID to 0. So it's not at all surprising that the clearInterval function isn't working.
You need to store that variable outside of the entire click function, so it's accessible the next time the event is fired. Also, else will suffice. There's only 2 possible options; if the first check returns false then you know it isn't checked - you don't need to test it.
var intervalID = 0;
$('input[type="checkbox"]').click(function(){
if ( $(this).is(":checked") ) {
intervalID = setInterval( next, 400 );
}
else {
clearInterval( intervalID );
}
});

setTimeout inside while loop

I've searched for how to use setTimeOut with for loops, but there isn't a lot on how to use it with while loops, and I don't see why there should be much difference anyway. I've written a few variations of the following code, but this loop seems to crash the browser:
while(src == '')
{
(function(){
setTimeout(function(){
src = $('#currentImage').val();
$("#img_"+imgIdx).attr('src',src);
}, 500);
});
}
Why?
Basically I have an image created dynamically whose source attribute takes time to load at times, so before I can display it, I need to keep checking whether it's loaded or not, and only when its path is available in $('#currentImage'), then do I display it.
This code worked fine before I used a while loop, and when I directly did
setTimeout(function(){
src = $('#currentImage').val();
$("#img_"+imgIdx).attr('src',src);
}, 3000);
But I don't want to have to make the user wait 3 seconds if the loading might be done faster, hence I put the setTimeOut in a while loop and shorted its interval, so that I only check for the loaded path every half second. What's wrong with that?
The while loop is creating trouble, like jrdn is pointing out. Perhaps you can combine both the setInterval and setTimeout and once the src is filled, clear the interval. I placed some sample code here to help, but am not sure if it completely fits your goal:
var src = '';
var intervalId = window.setInterval(
function () {
if (src == '') {
setTimeout(function () {
//src = $('#currentImage').val();
//$("#img_" + imgIdx).attr('src', src);
src = 'filled';
console.log('Changing source...');
clearInterval(intervalId);
}, 500);
}
console.log('on interval...');
}, 100);
console.log('stopped checking.');
Hope this helps.
The problem is probably that you're not checking every half second.
setTimeout schedules a function to run at a future time, but it doesn't block, it just runs later. So, in your while loop you're scheduling those functions to run just as fast as it can iterate through the while loop, so you're probably creating tons of them.
If you actually want to check every half second, use setInterval without a loop instead.
Thanks everyone - all the suggestions helped. In the end I used setInterval as follows:
var timer;
// code generating dynamic image index and doing ajax, etc
var checker = function() {
var src = $('#currentImage').val();
if(src !== '') {
$('#img_' + imgIdx).attr('src', src);
clearInterval(timer);
}
};
timer = setInterval(checker, 500);

What is the correct way to do an infinite loop that calls a method in Jquery or Javascript?

I have a page that I want to update non stop, every few seconds.
For this, I wrote the following:
var to;
$(function () {
to = setTimeout(updateDivContent, 2000);
});
function updateDivContent() {
$('#topbox').load('/home/blabla', null);
$('#leftgraph').load('/home/blabla', null, function () {
to = setTimeout(updateDivContent, 2000);
});
};
This worked, however, it leads to what I presume is a memory leak as after around 15 minutes, the computer almost freezes up with the browser taking up all available memory and CPU.
I am guessing that the Timeout is basically stacking, but, I am not sure how to fix this. I have tried getting rid of the second timeout and putting the first one inside a while(true) loop, but, I just couldn't get it to work.
Can anyone suggest anything?
This looks fine actually. But if the first Ajax call does not finish within two seconds, it will stack, and this could (don't know for sure) cause problems.
The timeout itself does not stack, since you are initiating a new one only after the previous one finished.
Try to initiate a new timeout once both Ajax requests finished:
$.when($('#topbox').load('/home/blabla'),
$('#leftgraph').load('/home/blabla')
).then(function () {
setTimeout(updateDivContent, 2000);
});
Reference: $.when
I think it is better to use setInterval instead of setTimeOut.
See this post.
You probably want to call clearTimeout to invalidate the previous timer, like this:
clearTimeout(to);
to = setTimeout(updateDivContent, 2000);
can you this it will call ever 2 second
to = setInterval("updateDivContent", 2000);
function updateDivContent() {
$('#topbox').load('/home/blabla', null);
$('#leftgraph').load('/home/blabla', null, function () {
//to = setTimeout(updateDivContent, 2000);
});
};
Try setInterval:
var to;
$(function () {
to = setInterval(updateDivContent, 2000);
});
function updateDivContent() {
$('#topbox').load('/home/blabla', null);
$('#leftgraph').load('/home/blabla')
};

setTimeout delay doesn't wait for the timeout

I trying to wrap my head around setTimeout, but I can't get it to work properly.
I have set up an example here: http://jsfiddle.net/timkl/Fca2n/
I want a text to countdown after an anchor is clicked - but my setTimeout seems to fire at the same time, even though I've set the delay to 1 sec.
This is my HTML:
Click me!
<span id="target"></span>
This is my JS:
$(document).ready(function() {
function foo(){
writeNumber = $("#target");
setTimeout(writeNumber.html("1"),1000);
setTimeout(writeNumber.html("2"),1000);
setTimeout(writeNumber.html("3"),1000);
};
$('a').click(function() {
foo();
});
});
setTimeout takes a function as an argument. You're executing the function and passing the result into setTimeout (so the function is executed straight away). You can use anonymous functions, for example:
setTimeout(function() {
writeNumber.html("1");
}, 1000);
Note that the same is true of setInterval.
You need to wrap your statements in anonymous functions and also stagger your timings -
setTimeout(function(){writeNumber.html("1")},1000);
setTimeout(function(){writeNumber.html("2")},2000);
setTimeout(function(){writeNumber.html("3")},3000);
If you set everything to 1000 the steps will pretty much run simultaneously as the setTimeout function will run the task 1 second after you called the function not 1 second after the previous call to the setTimeout function finished.
Demo - http://jsfiddle.net/JSe3H/1/
You need to use a function reference to be invoked later when the timer expires. Wrap each statement in an anonymous function so that it isn't executed immediately, but rather when the timer expires.
setTimeout(function() { writeNumber.html("1"); },1000);
Also, you want to use a different delay value for each one so that the timers don't expire at the same time. See an updated fiddle at http://jsfiddle.net/RqCqM/
You need tot use a functions to be called after the timeout is passed; you can use anonymous function too, then your function foo will look like this:
function foo(){
writeNumber = $("#target");
setTimeout(function() { writeNumber.html("1"); },1000);
setTimeout(function() { writeNumber.html("2"); },1000);
setTimeout(function() { writeNumber.html("3"); },1000);
};
There is a provision to pass arguments to the function. In your case, you can do it by
setTimeout(writeNumber.html,1000,1);
setTimeout(writeNumber.html,1000,2);
setTimeout(writeNumber.html,1000,3);
third argument to setTimeout function will be pass to writeNumber.html function
Just use setInterval(). Here's what I came up with. Here's your new javascript:
function foo(){
writeNumber = $("#target");
number = 0;
writeNumber.html(number);
setInterval(function(){
number = number+1;
writeNumber.html(number);
},1000);
};
$('a').click(function() {
foo();
});
I landed on this question. It has been answered adequately, and I think using setInterval as #Purag suggested is probably the best approach to get the desired functional behaviour. However the initial code example did not take JavaScript's asynchroneous behaviour into account. This is an often occurring error, which I've made myself on more than occasion :).
So as a side note I wanted to give another possible solution for this which mimics the initial attempt, but this time DOES consider Javascript's Asynchronousity:
setTimeout(function() {
writeNumber.html("1");
setTimeout(function() {
writeNumber.html("1");
setTimeout(function() {
writeNumber.html("1");
}, 1000);
}, 1000);
}, 1000);
Now ofcourse this is clearly terrible code!
I have given a working JSFiddle of it in my own SO question. This code exemplifies the so-called pyramid of doom. And this can be mitigated by using JavaScript promises, as shown in the answers to my question. It takes some work to write a version of WriteNumber() that uses Promises, but then the code can be rewritten to somehting like:
writeNumAsync(0)
.then(writeNumAsync)
.then(writeNumAsync)
.then(writeNumAsync);

Categories