Eddie Tseng Eddie Tseng - 2 months ago 17
AngularJS Question

$timeout use inside AngularJS factory

I used AngularJS factory to create new instance model for my project, and each model contain a progress value that will be incremented, paused, and set back to 0 based on "start", "pause", and "stop" user actions.

app.factory('ModelA', ['$timeout', function($timeout) {
function ModelA(progress) {
this.progress = progress;
};

ModelA.prototype = {
startProgress: function() {
this.counterFunction();
},
counterFunction: function() {
this.progress++;
if(this.progress == 100) {
this.progress = 0;
}
//console.log(this.progress);
//console.log(this.counterFunction);
progressTimeout = $timeout(this.counterFunction, 1000);
},
// Haven't tested the method below
pauseProgress: function() {
$timeout.cancel(progressTimeout);
},
stopProgress: function() {
$timeout.cancel(progressTimeout);
this.progress = 0;
}
};
return ModelA;
}]);


For some reason, when I call
startProgress()
in the
ng-click
expression function, the progress will increment 1 and then stop. I added logs to check
this.counterFunction
for every call. I realized it only prints out
1
and the whole
counterFunction
on the first time. As for the second time,
this.progress
will be
NaN
and the counterFunction will show
undefined
.

I'm new to AngularJS, could someone please help me out? Thanks.

Answer

The this object in the function called by the $timeout, i.e. this.counterFunciton is not the ModelA instance, therefore you should use $timeout(this.counterFunction.bind(this), 1000) instead.

You can read up this article about binding this object in JavaScript.

A working codepen for your reference.