Arun Karnawat Arun Karnawat - 1 year ago 59
Javascript Question

Why setInterval not stoped by clearInterval

var progressbar = {
progress : null,
html : function() {
var loadingHtml = '<div id="loader-wrapper" class="catalog-loadmore">';
loadingHtml += '<div class="progress"><div id="catalog-bar" class="progress-bar progress-bar-striped active" style="width: 10%"></div></div>';
loadingHtml += '<div class=""><span id="progress-valuenow"></span>%</div>';
loadingHtml += '</div>';
return loadingHtml
},
start : function() {
var width = 10;
this.progress = setInterval(function() {
$('#catalog-bar').css('width', width + '%');
$('#progress-valuenow').text(width);
if(width < 98){
width += 1;
}else{
this.stop(); // this is not working
clearInterval(this.progress); // this is also not working
console.log('else')
}
}, 100);
},
stop : function() {
clearInterval(this.progress);
},
destroy : function() {
clearInterval(this.progress);
$('#loader-wrapper').remove();

}
}


In the above code, why the following statement not working the else condition is executed
console.log('else')
is printing but clearInterval() not working. I am calling progressbar.destroy() from outside and it is working.

this.stop(); // this is not working
clearInterval(this.progress); // this is also not working


Can any one tell me what i that i am doing wrong.

Answer Source

You've passed anonymous function into setInterval, anonymous functions has context this setted to window, so you are targeting window.progress.

You have two ways to solve your problem:

  • store this in some variable like var _this = this; setInterval(function() { ... clearInterval(_this.progress) } ...)

  • use Function.prototype.bind() to set context of your anonymous function like setInterval(function() { ... clearInterval(this.progress) }.bind(this) ...)


Or set up transpiler for ES6 and use Arrow function which binds this automatically