How is setInterval invoked here? - javascript

I have the following Javascript code attached to an HTML document with some CSS styling.
It is simply a box on the screen that changes the style background property colour according to those seen in the array. The id of "colour-changer" is used to access the HTML document and changes it each time the array is iterated.
The function declaration changeColour(); is used to make this happen by using colours.length to count its way through the array and then puts the array value into the HTML, which changes its background colour every 3 seconds.
Once it comes to the end of the array the counter is reset to 0, and it continues around again.
The setInterval method invokes the callback method changeColour() every 3 seconds to make this happen.
In order to stop the cycle, an onclick is event is added which invokes a clearInterval() method to print out "Timer stopped" inside the box. In order to do this the setInterval() method had to be stored in variable myTimer.
See the code below. It all works fine but this is not my real problem.
let colourChanger = document.getElementById ("colour-changer");
let colours = ["red","blue","green","pink"];
let counter = 0;
function changeColour(){
if (counter >= colours.length){
counter = 0;
}
colourChanger.style.background = colours[counter];
counter++;
}
let myTimer = setInterval(changeColour, 3000);
colourChanger.onclick = function (){
clearInterval(myTimer);
colourChanger.innerHTML = "Timer stopped";
}
What I cannot understand is the line let myTimer = setInterval(changeColour, 3000);
From my understanding if you store a function inside of a variable, it will NOT execute unless called separately. It will just sit there stored in the variable myTimer.
There is no setInterval(); call made outside of the variable anywhere.
MY QUESTION:
How then is this method invoked since it is simply stored inside of the variable myTimer?

No, your understanding is wrong.
It executes setInterval(changeColour, 3000); and stores this particular interval reference ID to myTimer to later be used in clearInterval(myTimer)
var myTimer = setInterval(() => console.log('ping'), 3000);
setTimeout(() => clearInterval(myTimer), 10000);
console.log('myTimer value: ', myTimer);

In order to do this the setInterval() method had to be stored in variable myTimer.
No, the return value of setInterval is stored in myTimer by that code. setInterval is called (it has (/*...*/) after it, which calls it).
From my understanding if you store a function inside of a variable, it will NOT execute unless called separately.
That's correct, but that's not what that line of code is doing. This code:
let myTimer = setInterval(changeColour, 3000);
calls setInterval and stores its return value in myTimer, exactly the way:
let x = example();
calls example and stores its return value in x.
It's the changeColour function that is only referenced, not called, by that code (there's no (/*...*/) after it). Doing that passes changeColour into setInterval, so that setInterval knows what function to call every three seconds or so.
So in that code, setInterval is called, and changeColour is just referenced (it's called later by the timer mechanism).

setInterval() function will return IntervalID, It will set execution interval for given milliseconds.
In your case once this line is executed it will start executing changeColour function every 3000ms / 3 seconds and return IntervalID.
Now this IntervalID is used to stop executing your function every 3 seconds in the future.
to stop executing you can use clearInterval(IntervalID).
if any doubts please comment.

Related

set Interval in javascript

I am beginner in javascript.
There is strange thing in javascript and I feel stupid
//First statement
var myVar = "Hello";
function hello() {
document.getElementById("demo").innerHTML = myVar;
}
//second statement
var myVar = setInterval(myTimer, 1000);
function myTimer() {
document.getElementById("demo").innerHTML = new Date().toLocaleTimeString();
}
Why the second function work without invoked it ?
Unlike the first ? This caused a lot of problems to me !
Why the second function work without invoked it ? Unlike the first ?
You are passing the function myTimer to setInterval. setInterval calls the function every 1000ms. So while it is not you who directly calls the function, it is still called (by setInterval). setInterval's whole purpose is to call the function that you pass to it as argument.
In contrast, you are not doing anything with hello. You are neither calling it directly, nor are you passing it to any other function that could call it.
From what I can gather from the comments, you seem to be confused as to why the myTimer() function works. Here's a brief explanation:
On this line
var myVar = setInterval(myTimer, 1000);
you are calling the setInterval() function. That function takes 2 parameters, which you have defined. The first one is a function; the code to be executed. The second one is the delay between each execution of said function.
On the next line, you have declared the variable myTimer to be a function which is executed with the setInterval.
Have a look at the MDN documentation for details. Specifically, it says:
var intervalID = window.setInterval(func, delay)
The parameters are defined as:
func: A function to be executed every delay milliseconds.
and
delay: The time, in milliseconds (thousandths of a second), the timer should delay in between executions of the specified function or code.

How to execute a function before waiting with setInterval in JavaScript?

When using setInterval(f, time), is it possible that the function f is executed first before waiting for a time?
Not within the setInterval function itself. Just call it explicitly.
f();
setInterval(f, time);
Note : Even if you set an interval. It is not assured that the function will be triggered on time because javascript is single threaded and it will wait until the current executing function in the stack finishes.
The function passed inside setInterval wont fire the first time inside the setInteral. we have to invoke the function manually.
func();
setInterval(func, time);
If You want the function to be triggered before waiting x time, and then execute again after said time, and again and again, you have to explicitly call the function f before starting the interval like so:
var f = function () {
document.write('<p>Function executed</p>');
}
f();
setInterval(f, 3000);
Mind that the time is in milliseconds, so if you want the function to repeat every 1 seconds you should use the number 1000.
If you want the interval to be more precise consider putting it in a web worker, however support is not available in all browsers.

Variable Scope with setTimeout & clearTimeout

While studying variable scope there has been one thing I can't seem to figure out. For example of two elements. If the first is hovered upon then its sibling appears. If you mouse-out of the initial element the sibling will disappear through a setTimeout which is stored within a variable expression. If you happened to hover over the sibling a clearTimeout function is called and is set to fade out in the callback.
In regards to scope what I'm not understanding is how exactly the timer variable is recognized in the clearTimeout function. I tried to console.log(timer) but just got numeric values. While the following works I'd like to know why and how? In other words how does the second hover method call know what's inside the timer variable since its out of scope?
var timer;
$('p:eq(1)').hide();
$('p').first().hover(function() {
$(this).next().fadeIn();
}, function() {
timer = setTimeout(function() {
$('p:eq(1)').fadeOut();
}, 1000);
// console.log(timer);
});
$('p:eq(1)').hover(function() {
clearTimeout(timer);
}, function() {
$('p:eq(1)').fadeOut(1000);
});
The function clearTimeout takes not just a setTimeout, but its ID. Here's what I found it on MDN:
So, when you set a timeout, it returns a specific ID for reference and so clearTimeout will work. Again, per MDN:
Since you set timer on the global scope, each of your functions has access to it.
Thanks for asking a question that taught me something! (I didn't know setTimeout returned anything)
Simple.. The timer itself is stored in memory though the 'timer' variable which you have defined in the same scope as the sibling event bindings. Therefore, the timer variable is acccessable by directly calling it with 'timer' in any sibling or child scopes. Had you declared the 'var timer' part within the function like this:
function() {
var timer;
timer = setTimeout(function() {
$('p:eq(1)').fadeOut();
}, 1000);
The result would be that clearTimeout(timer) would not be within the scope and result in an unknown member error.

Javascript variable not displaying in simple HTML script

I'm trying to have a simple html page that counts up indefinitely. But for some reason my second variable is not being displayed. The second variable is an embedded javascript timer As you can see the first variable is displayed, but not the second. Apologies, I'm a beginner.
https://dl.dropboxusercontent.com/u/44188718/time.html
<script>
var test;
test = 123;
</script>
<script>document.write(test)</script>
<script>
var time;
time = 0;
function startTimer()
{
window.setTimeout(add(), 60 * 1000);
}
add()
{
var += 1;
}
</script>
<script>document.write(time)</script>
Your middle script element contains several errors.
This line:
window.setTimeout(add(), 60 * 1000);
should be:
window.setInterval(add, 60 * 1000);
setTimeout() calls a function exactly once. setInterval() calls a function repeatedly. Also note that I've removed the () after add - with parentheses it calls the function immediately and passes its result to setTimeout() or setInterval(), but you want to pass the function itself so just use the function name with no parentheses. (And the window. part is optional).
Then this line:
add()
should be:
function add()
And this:
var += 1;
should be:
time += 1;
// OR
test += 1;
(I'm not sure which variable you intend to increment.)
Also you never call the startTimer() function.
Finally, in your add() function you'd need to actually output the value. document.write() is almost never a good idea, so I'd suggest creating an element on your page to hold the number and updating its content:
<div id="timer"></div>
document.getElementById("timer").innerHTML = time; // or = test; (whichever var you want)
Demo of all of the above: http://jsfiddle.net/Y3XMk/
Or the same effect with simplified code: http://jsfiddle.net/Y3XMk/1/
There are several misconsceptions in your code, so I will try to go through them.
You have to specify the function keyword when you define a function. In your case:
add(){ ... }
Should be:
function add() { ... }
Then you can safely call it from your setTimeout code.
Using the keyword var you are basically telling that you are about to define a variable for the current scope. First of all, since the current scope is window anyways (the global scope), you don't need to add var. Secondly, you have to use the variable name when you change it, or add to it. In your case:
var += 1
Should be:
time += 1
Functions get called once, when you call them. In your case, document.write(time) will get called once when the document is parsed, and hence will write 1 in your document. You have to call the write method inside your add function, to have numbers show up at every interval. So:
function add(){
time += 1;
document.write(time);
}
setTimeout calls the specified callback function once, after the time is passed, I believe you are looking for setInterval. You can use it like so:
function startTimer(){
window.setInterval(add, 60 * 1000);
}
But don't forget to call your function, in order for the timer to start.
Here is an example of your code (it works every second instead):
Working fiddle
There are a lot of things wrong with your code.
I believe what you are trying to do is this:
<script>
var time = 0;
window.setInterval(function(){
document.write(time);
time++;
}, 60*1000);
</script>
See a working demo here:
http://jsfiddle.net/8MVFB/
Just click "Run".

How to figure out how to use setInterval correct with this jQuery script

This is a continuation of a previous question I asked.
I'm trying to display a clock based on a pre-determined time value .. not the current clients time.
Here's my jQuery:
$(document).ready(function () {
var currentTime = new Date('3/09/2010 9:27:29 PM');
setInterval("DisplayTime(currentTime, $('.answer-body'))", 1000);
})
function DisplayTime(currentTime, destination) { ... }
Now inside the DisplayTime function, i was showing some custom text, calling the destintion.html(..) to display that custom text. And finally, after I display the text, I was thinking of adding 1 second to currentTime so when the next iteration of the interval, it's not using the original time value, but 1 second later.
Problem: I cannot pass in the currentTime variable to the setInterval function. I don't particularly want to have an anonymous function here, unless I have no choice.
How can I refactor my bad code?
So every second, the time is re-displayed with the new second being added.
On the contrary, you should use an anonymous function here, like this:
setInterval(function() {
DisplayTime(currentTime, $('.answer-body'));
}, 1000);
Don't ever pass a string to setInterval() or setTimeout() if you can avoid it, it performs an eval() and has scope issues, like the one you're currently experiencing, since currentTime isn't a global variable.
$(document).ready(function () {
var currentTime = new Date('3/09/2010 9:27:29 PM');
var destination = $('.answer-body');
function DisplayTime()
{
destination.html(currentTime);
currentTime.setTime(currentTime.getTime() + 1000);
}
var id = setInterval(DisplayTime, 1000);
})
This uses a function (closure) within a function, but not an anonymous one. DisplayTime will not be accessible from outside scopes. There's no real reason to dislike anonymous functions, used appropriately. I would use one here.

Categories

Resources