AngularJS - Can't cancel $interval after initiating it twice

I'm new to programming, and have recently been playing around with AngularJS.

To practice, i've decided try and create a simple stopwatch.

Starting with an initial 'time' value of 0, i'm using $interval to increment the 'time' by 0.01, every 10 milliseconds. I can start and stop the stopwatch without any issues, UNLESS i click 'Start' twice. After doing so, 'Stop' no longer works.

I'm sure this is an awful way to create a stopwatch, but regardless, the issue still remains.

My html contains the timer and 'Start' and 'Stop' buttons, like so:

<div class="row" style="margin-left: 20px" ng-controller="timerCtrl">      
  <b>{{time | number : 2}}</b>
  <button ng-click="startTimer()">Start</button>
  <button ng-click="stopTimer()">Stop</button>
</div>

And the js:

.controller('timerCtrl', ['$scope', '$timeout', '$interval',
  function($scope, $timeout, $interval) {

  $scope.time = 0;       

  $scope.startTimer = function() {
    $scope.counter = $interval(function(){
    $scope.time += 0.01;
    }, 10)  
  }

  $scope.stopTimer = function() {
    $interval.cancel($scope.counter);
  }
 }
])

What's the best way to solve this? Any help will be much appreciated, thanks!

The problem is that $interval returns a promise, and each time you run $scope.startTimer you are creating a new promise. When you run it a second time, it doesn't cancel the previous promise, it just re-assigns $scope.counter to the new promise.

Check out the AngularJS $interval page to see their example and method of avoiding this problem.

A simple solution is to check to see whether the var you're assigning your promise to has already been defined when you are about to create a new promise. For example:

if ( angular.isDefined($scope.counter) ) return;

You can also use a boolean var to maintain the status as to whether it has been started or not if you prefer that.