1

I am doing a project in angularjs (1.x). My requirement is that I need to count the number of seconds elapsed.

For that, I have written a code using $interval service in my controller which is working perfectly fine.

Now , since this code is shared by many objects, so I thought to make it singleton. How can we do so?

Below is my code inside controller:

scope.timeDiff = 0;
 var intervalId = $interval(function(){
           scope.timeDiff += 1000; 
        },1000);

 scope.$on('$destroy',function(){
           $interval.clear(intervalId);
 });

I have tried to create a service of timer like this:

angular.module('myModule').factory('customTimer', ['$interval','$rootScope',
  function ($interval,$rootScope) {
     var timerId, defaultInterval = 1000;     
     return {
       startTimer: function (timeDiff) {
        $interval(function(){
           timeDiff += 1000;
        },1000);
        return timeDiff;
       }
     };
}]);

And then I try to call this service in my controller like this:

scope.timeDiff = customTimer.startTimer( scope.timeDiff);        
console.log( "new timediff:",scope.timeDiff );

While timeDiff is updating in my timer service, but controller is always getting 0. What could be the reason?

Anubha Gupta
  • 189
  • 2
  • 17

1 Answers1

1

First of all angular service and factory is already singleton.

The only problem is a synchronization problem.

Its asynchronous call, so you have to ensure it by using callback or promise.

In controller add the following methods:

$scope.callback = function(retTime) {
  console.log( "new timediff:",retTime);
}
$scope.timeDiff = customTimer.startTimer( scope.timeDiff, $scope.callback);   

$scope.$on('$destroy',function(){
       customTimer.stopTimer();
}); 

The factory can be written as follows:

angular.module('myModule').factory('customTimer', ['$interval','$rootScope',
  function ($interval,$rootScope) {
     var timerId, defaultInterval = 1000;     
     return {
       startTimer: function (timeDiff, callback) {
        timerId = $interval(function(){
           timeDiff += 1000;
        // This if block will ensure your controller callback called after the value of time diff is updated.
           if(callback) {
              callback(timeDiff)
           }
        },1000);
        return timeDiff;
       },
       stopTimer: function () {
         $interval.cancel(timerId);
       }
     };
}]);

The angular service can be written as follows:

angular.module('myModule').service('customTimer', ['$interval','$rootScope',
  function ($interval,$rootScope) {
     var self = this;
     self.defaultInterval = 1000;     

       self.startTimer = function (timeDiff, callback) {
        self.timerId = $interval(function(){
           timeDiff += 1000;
        // This if block will ensure your controller callback called after the value of time diff is updated.
           if(callback) {
              callback(timeDiff)
           }
        },1000);
        return timeDiff;
       }
       self.stopTimer = function () {
         $interval.cancel(self.timerId);
       }

}]);
I. Ahmed
  • 2,438
  • 1
  • 12
  • 29
  • Your solution is working fine. Thank you so much. Could you please edit the code of service and add the code for destroying/clear the interval ? – Anubha Gupta May 25 '18 at 09:47
  • Please check the answer is updated with destroying and clear the interval – I. Ahmed May 26 '18 at 13:57