I am using a timer to call a function after 1 minute.
var timer = setTimeout(function() {
console.log("timer trigger");
}, 10000);
clearTimeout(timer); clears the timer and delete timer; returns false.
Why delete is not working with timers?
delete timer; won't actually do anything, because you can only delete object properties. timer is not an object property, so it can't be deleted. (Technically it's a property of the window object, but Javascript specifies that unless you assign window.timer then you can't delete top level variables). When delete returns false that means there was nothing to delete.
The timeout you've set is a function reference. That's what needs to be removed, not the integer returned by setTimeout. Only the runtime environment (browser) knows how to remove that function reference by its id, which is what's returned from setTimeout.
Related
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.
I am trying to know what is the value of the variable when setTimeout get called and assigned to it. Unexpected value get logged, so being curious how this happening.
I tried to look some related question on stack and also look out on web but didn't get the exact answer.
Update - I am seeking help to understand how the unique id which assigne d to variable get calculated ?
let a = setTimeout( () => {
console.log('something will happen')
}, 2000)
let b = setTimeout( () => {
console.log('something will happen')
}, 3000)
let c = setTimeout( () => {
console.log('something will happen')
}, 4000)
console.log(a, b, c)
There is documentation on what type of values to expect.
Quote:
The returned timeoutID is a positive integer value which identifies the timer created by the call to setTimeout(); this value can be passed to clearTimeout() to cancel the timeout.
It may be helpful to be aware that setTimeout() and setInterval() share the same pool of IDs, and that clearTimeout() and clearInterval() can technically be used interchangeably. For clarity, however, you should try to always match them to avoid confusion when maintaining your code.
It is guaranteed that a timeout ID will never be reused by a subsequent call to setTimeout() or setInterval() on the same object (a window or a worker). However, different objects use separate pools of IDs.
When you call setTimeout or setInterval the uniq id of particular timer is returned.
Usually it is just a number, incremented with every new timer and it is guaranteed that this number will never be reused.
You can use it only for cancelling timeouts or intervals with corresponding function clearInterval or clearTimeout.
More about returned value here.
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.
I am trying to set my localStorage key values after a certain condition becomes true but wait for 2 seconds before it can update the localStorage key value
This is what I am trying to do but it throws an exception and when it tries to set the localStorage value
if(tempArray.length <= 0){
setTimeout(function(){
this.storage.set(achkey,1);
},2000);
}
The exception says variable achkey undefined though I can use it outside the setTimeout function. How do I go about implementing the delay and setting values inside correctly? I am using ImpactJS engine which uses javascript. I am also using a plugin for my localStorage.
You need to cache this. Once you enter the setTimeout's anonymous function, this now refers to the scope of the function that you just declared.
if(tempArray.length <= 0){
var self = this; // Cache the current scope's `this`
setTimeout(function(){
self.storage.set(achkey,1);
},2000);
}
Here's a link with some sample code.
http://jsfiddle.net/4djNt/2/
I assumed, until I started testing, that the return value of a setTimeout() would be some kind of browser object.
In fact it seems to be a simple integer. I also believed that assigning the return value of setTimeout to a global variable would mean that there could only be one such object. But as you'll see if you click the "start timer" button more than one, there can be multiple timers running concurrently.
For instance
I click the start button
the script creates a timeout
it is timeout 1, due to fire in five seconds
one second later, I click again and now there's a timeout 2
now I have timeout 1 due to fire in four seconds and timeout 2 in five seconds
I click the stop button and only timeout 2 is cleared
The problem of user clicks creating multiple timers can be solved by always clearing the current timeout var before setting it. But I would really like to understand what Javascript is doing actually doing here.
setTimeout and setInterval return a number. The number is the id of the timer. Active timers can be stopped using clearTimeout and clearInterval respectively.
If you lose the timer's id, you'd either have to guess it again, or wait for it to complete (assuming it's a timeout).
If the timer hasn't been cancelled in the number of milliseconds specified in the delay parameter, it will execute the callback function in the global context.
The return value of setTimeout can be passed to clearTimeout to prevent a scheduled task from running. If the variable has been set and your button is pushed again, run clearTimeout first, then setTimeout assuming you want only the 2nd push to schedule.
The questioner asks only about timeout objects, which are returned in lieu of numbers in some environments, for instance timeoutObject. For purposes of canceling the callback, passing the entire timeout object to clearTimeout(toObj) does the trick.
{
called : bool
_idleTimeout : null
_idlePrev : null
_idleNext : null
_idleStart : null
_onTimeout : function (){}
_repeat : null
unref : function () {}
ref : function () {}
close : function () {}
}