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?

9
  • Possible duplicate of Are Angularjs services singleton? Commented May 25, 2018 at 5:28
  • Angular service is singleton, you don't need to make it singleton Commented May 25, 2018 at 5:31
  • @huanfeng Please see the edits Commented May 25, 2018 at 5:47
  • @KaustubhKhare: Please see the edits Commented May 25, 2018 at 5:47
  • In your service, you are returning timeDiff. It will return immediately. when you called startTimer function. It will not wait till 1 sec. Commented May 25, 2018 at 5:59

1 Answer 1

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);
       }

}]);
Sign up to request clarification or add additional context in comments.

2 Comments

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 ?
Please check the answer is updated with destroying and clear the interval

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.