clearInterval doesn't clearInterval - javascript

var timer;
function check_element_load(){
timer = window.setInterval(function(){
console.log("still working"); // keeps running forever
if(document.getElementById("comments")){
console.log("FOUND"); // this actually runs
document.getElementsByTagName("fb:comments")[0].setAttribute('order_by', 'social');
window.clearInterval(timer); // < not effective
}
}, 50);
}
check_element_load();
I'm trying to put a script on top to keep checking if a specific element was successfully loaded in the browser, it works (the console logged " FOUND "), but when I wrote another console log to see if the interval still running. it does, it never stops and the clearInterval is completely ignored
is there anything that I missed ? I also tried using all other solutions including settimeout and the closest one to me now is the written, I just want the clearinterval to take effect after the condition returns true.
Is there anything similar to clearinterval that is more effective, kills the whole function or something?

As it stands, your code is logical correct, however if
document.getElementsByTagName("fb:comments")[0].setAttribute('order_by', 'social');
throws an error, (of course) the timeout will never be cleared. You could use SetTimeout instead.
Most likely calling getElementsByTagName("fb:comments") returns an empty set, giving you an "method setAttribute does not exist on Element undefined" Type Error.

Related

Why would 'clearTimeout' not work in this scenario?

I'm having an issue stopping the 'gameTimer' timer from running with 'clearTimeout()' in my code. I have simplified part of my code here to only contain the necessary details.
//This runs when someone connects to my website
io.on('connection', function (socket) {
let gameTimer;
//Runs the in-game timer
function questionCountdown() {
gameTimer = setTimeout(function () {
//Reveal if the players' answers are right or wrong
revealAnswer(answeredPlayers, playerData[socket.id].room);
//Start the countdown for the next question
countToNextQuestion(playerData[socket.id].room);
}, 21000)
}
//Starts the game
socket.on('Request Game Start', async function (room) {
questionCountdown();
})
//Runs when a player has answered(ignore the function arguments)
socket.on('Answered Question', function () {
//If all users in the room have answered...
if (answeredPlayers.get(playerData[socket.id].room) == (roomMap.get(playerData[socket.id].room)).length) {
//Stop the count[THE MAIN ISSUE]
clearTimeout(gameTimer);
//Reveal if the players' answers are right or wrong
revealAnswer(answeredPlayers, playerData[socket.id].room);
//Start the countdown for the next question
countToNextQuestion(playerData[socket.id].room);
}
})
})
Is there any reason why the "clearTimeout()" used in socket.on('Answered Question', function () {would not work?
Possible reasons that the clearTimeout() doesn't stop a previously started gameTimer:
The socket.on('Answered Question', ...) event isn't happening when you think it is. Either it's never happening or it's happening too soon.
The condition if (answeredPlayers.get(playerData[socket.id].room) == (roomMap.get(playerData[socket.id].room)).length) isn't being met or throws and thus you never get to the clearTimeout().
You start more than one gameTimer for a given user before stopping one, thus the second overwrites the timer from the first and you then never stop the first one.
Your user leaves the web page or hits refresh and since you don't show listening for the disconnect event, you leave a gameTimer running that can never get stopped. FYI, this should be addressed whether it's the cause of the current problem you're looking at or not.
Since each socket.io connection has their own gameTimer, you are just confused about whether it is or isn't getting stopped and perhaps one gameTimer is getting stopped and you're just being fooled by the fact that there are others also running that belong to different connections.
FYI, you can figure out if any of these are the cause with appropriate console.log() statements and then studying the logs. These timing-sensitive, event driven problems are usually solved with detailed logging and then studying the logs to see exactly what did and didn't happen in your code and in what order.
In your code since the setting of the Timeout is triggered by an event, it might occur that clearTimeout get's called without gameTime being set. Also clearTimeout is being triggered by an event and if that event doesn't fire the timeout won't be cleared.
The problem might lie in the source of your events. Where or when do they get triggered?
You might also test your if statement. Put a console.log before calling clearTimeout and see if it get's run when you want it to.

setTimeout blocking issue

I'm writing a "Game of Life" in javascript. I have all the logic done in a function called doGeneration(). I can repeatedly call this from the console and everything goes as planned, however, if I put it in a while loop the execution blocks the UI and I just see the end result (eventually).
while (existence) {
doGeneration();
}
If I add a setTimeout(), even with a generation limit of say 15, the browser actually crashes (Canary, Chrome).
while (existence) {
setTimeout(function() {
doGeneration();
},100);
}
How can I call doGeneration() once every second or so without blocking the DOM/UI?
You want setInterval
var intervalId = setInterval(function() {
doGeneration();
}, 1000);
// call this to stop it
clearInterval(intervalId);
I would use requestAnimationFrame(doGeneration). The idea of this function is to let the browser decide at what interval the game logic or animation is executed. This comes with potential benefits.
https://hacks.mozilla.org/2011/08/animating-with-javascript-from-setinterval-to-requestanimationframe/
Rather than using setINterval or setTimeout and assume some random time interval will be enough for the UI to update you shoul/could make the doGeneration smart enough to call itself after dom was updated and if the condition of existence is satisfied.

clearInterval - something's amiss

It seems that everyone has a few problems with clearInterval. I have built a slider that allows people to hover a click on arrows. The banner also rotates ever few seconds. I want to be able to have the auto-rotate turn off after someone clicks on one of the arrows.
Here's my code:
$(function(){
var intvl = 0;
intvl = setInterval(heroTransitionNext, 2000);
$('.rightArrow').click(function(){
window.clearInterval(intvl);
});
});
EDIT:
Here is the function it is calling:
function heroTransitionNext() {
$('.HP-hero li').filter(':visible').fadeOut('normal', function () {
if ($(this).next().length != 0) {
activeZone = parseInt(activeZone) + 1;
$(this).next().fadeIn('normal', heroNavHighlight(activeZone));
} else {
activeZone = 1;
$('.HP-hero li:first-child').fadeIn('normal', heroNavHighlight(activeZone));
}
$(this).hide();
});
};
To stop the animation you can use jquery's .stop() but not sure whether it'll solve the problem or not that you are facing (didn't visualize) but you can give it a try
$('.HP-hero li').stop(1,1); // or try $('.HP-hero li').stop()
window.clearInterval(intvl);
As say2joe said that clearInterval will just stop the function from invoking next time but it won't clear the current queue (he is right) so in that case stop could be used.
About Stop.
Depending on how much work your heroTransitionNext function is doing, it may still be executing even though the interval is cleared -- in other words, clearing the interval will stop the function from being invoked -- but, any instance of the function(s) executing in memory will continue to execute until finished.
To be more clear, here's a use case (you can check this out yourself by using a profiler in Firebug or Developer Tools):
heroTransitionNext execution time is 2.1 seconds.
clearInterval is invoked 6.1 seconds after setInterval is invoked.
At 6.1 seconds, heroTransitionNext has been invoked four times. The first three executions have completed, however, the fourth will not complete until it finishes executing (at 8.1 seconds since setInterval was called). Note: In this use case, each successive invokation will execute while the last invokation's execution is still continuing (for 100 more ms) -- in other words, you'll have execution overlap from 2 to 2.1, 4 to 4.1, and 6 to 6.1 second intervals.
If the function takes longer to execute than the interval set, use a recursive function with setTimeout(). The following link will give you a good example.
Also, a good reference for explanation is https://developer.mozilla.org/en/DOM/window.setInterval.

Resetting setTimeout object if exists

When somebody clicks my checkboxes, from a long list of checkboxes, I want to show the number of selected checkboxes in a little popup element. My problem is, the little popup element should disappear 5 seconds after the last click, which is OK for one checkbox being clicked, but if I quickly check 5 boxes, the timer is still set on the first box, resulting in the popup element disappearing too quickly.
As you can see in my function, I've tried using the clearTimeout(timeoutName) function but have experienced some troubles applying it. The console log states that the clearTimeout(timeoutName) is undefined, which I can understand: the setTimeout hasn't even started yet.
How can I check that the timer exists before I clear it? Or is this really not the best method? When a checkbox is checked (this function runs) there could be a timer running but sometimes there could not be.
$('.name_boxes').live('click', function() {
var checked_count = $('.name_boxes:checked').length;
// other stuff
clearTimeout(hide_checked_count_timer); // if exists????????
$(".checked_count").hide();
$(".checked_count").text(checked_count+" names selected");
$(".checked_count").show();
hide_checked_count_timer = setTimeout(function() {
$(".checked_count").hide();
},5000);
});
Any help gratefully received...
Just declare the timer variable outside the click handler:
var hide_checked_count_timer;
$('.name_boxes').live('click', function() {
var checked_count = $('.name_boxes:checked').length;
// other stuff
clearTimeout(hide_checked_count_timer); // if exists????????
$(".checked_count").hide();
$(".checked_count").text(checked_count+" names selected");
$(".checked_count").show();
hide_checked_count_timer = setTimeout(function() {
$(".checked_count").hide();
},5000);
});
http://jsfiddle.net/kkhRE/
Considering .live has been deprecated, you should be delegating the event with .on instead:
// Bind to an ancestor. Here I'm using document because it an
// ancestor of everything, but a more specific ancestor
// would be preferred.
$(document).on('click', '.name_boxes', function() {
// ...
});
Q. The console log states that the clearTimeout(timeoutName) is undefined, which I can understand: the setTimeout hasn't even started yet.
A. The clearTimeout() function's return value is undefined regardless of whether there was a timeout to be cleared. It doesn't have a concept of "success" that can be tested. If there is a queued timeout associated with the id you pass then it will be cleared, otherwise nothing happens.
Q. How can I check that the timer exists before I clear it?
You can't, at least not in the sense of there being some registry of outstanding timeouts that you can query. As you already know, the .setTimeout() function returns an id for the timeout just queued, and you can use that id to clear it before it runs, but there is no way to test whether it has already been run. The id is just a number so the variable that you saved it in will continue to hold that number even after the timeout has either run or been cleared.
It does no harm at all to call clearTimeout() with an id for a timeout that already ran - basically if the timeout for that id is in the queue it will be cleared otherwise nothing will happen.
The easiest way to test "Is there an outstanding timeout that hasn't run yet" is to set the variable holding the timerid to null when the timeout runs, i.e., within the function you queued:
var timerid = setTimout(function() {
timerid = null;
// other operations here as needed
}, 5000);
// in some other code somewhere
if (timerid != null) {
// timer hasn't run yet
} else {
// timer has run
}
The variable you save the timerid in needs to be in a scope that can be accessed both where you set it and where you test it, i.e., don't declare it as a local variable within an event handler.
You can use the power of short-circuit operators
hide_checked_count_timer && clearTimeout(hide_checked_count_timer);
The right-hand statement will only run if the left-hand variable is not undefined.
to check if it exists use;
if (typeof timerid == 'undefined')
{
//timer has not been set so create it
timerid = setTimeout(function(){ var something = true;}, 5000);
}

javascript setTimeout, page looks like is endlessly loading (firefox)

var checkTextValue = setTimeout(function() {
var textVal = $('p').text();
if (textVal == 'expectedValue'){
callback();
} else {
setTimeout(arguments.callee, 10);
}
},10);
i have this code,it works just fine but the problem is that in firefox the page looks like is endlessly loading.
Looks kind of useless... I mean setTimeout(checkTextValue, 10); - what are you setting there? checkTextValue is just a timeout ID, nothing else... No idea why FF would load endlessly, simply because the code is faulty...
That is because it is endlessly loading. Basically you do recursion and start another instance every ten milliseconds. Given enough time, I think it also is possible to kill your browser with this code.
Try using an onchange-eventhandler on your input field instead.
I think its a case of recusrsion. Google 'recusrion' for more clues. Just kidding. checkTextValue will be running indefinitely unless the value is 'expectedValue'.

Categories

Resources