JavaScript clearTimeout not working
(I’ve looked at all similar questions/answers but none of them solve my problem.)
The code:
var timeoutHandle;
function showLoader(show) {
if (show) {
$('.loader').html('Loading...');
$('.loader').show();
timeoutHandle = setTimeout(function () {
if ($('.loader').is(':visible')) {
$('.loader').html('Still loading...');
}
}, 15000);
}
else {
$('.loader').hide();
clearTimeout(timeoutHandle);
}
}
The AJAX function simply calls showLoader(true)
before calling the server, and then showLoader(false)
after a result. I still sometimes see the text change from “Loading…” to “Still loading…” long before 15 seconds, so it’s as if a timer thread is still running. Is there something wrong with the code above? Or could the problem be with other code..
edit: I must add that showLoader(true)
can be called again (and again) before a response from the server
You should add a check to see if there is already a timeoutHandle
before creating a new one.
try this:
if(timeoutHandle){
clearTimeout(timeoutHandle);
timeoutHandle = null;
}
timeoutHandle = setTimeout(function () {
if ($('.loader').is(':visible')) {
$('.loader').html('Still loading...');
}
}, 15000);
and then in the else case set timeoutHandle
to null after you clear it like so:
clearTimeout(timeoutHandle);
timeoutHandle = null;
This will eliminate the chance of you creating concurrent timeouts if showLoader(true)
function is called more than once.
What might be happening is that you’re placing multiple calls to showLoader
since this is a global function you can access it from anywhere, you typically don’t want that.
I would consider changing it to a monad implementation:
function create_loader(elem) {
var handle = null;
function show() {
elem.html('Loading...');
elem.show();
if (handle !== null) {
clearTimeout(handle); // clear the previous one
}
handle = setTimeout(function () {
elem.html('Still loading...');
}, 15000);
}
return {
show: show,
clear: function () {
elem.hide();
clearTimeout(handle);
handle = null;
}
};
}
Usage:
var loader = create_loader($(".loader"));
loader.clear();
loader.show();
loader.show(); // each new call to show will reset the 15s timer
loader.show();
loader.show();
loader.clear();
// and you can make another one that operates independently of other one
var another_loader = create_loader($(".anotherLoader"));
Now you have a loader
object that knows about it’s own state.
In your post you mention that showloader can be called multiple times before the first return. This is your problem. You are overwriting an already existing timeoutHandle with a new one without destroying the already existing handle. You should check if the timeoutHandle is set or not set before you create a new one.
You don’t call clearTimeout(timeoutHandle) then starting new request, if timeoutHandle exist