5

I'm new to AngularJS. I'm currently looking at the $timeout service. I understand that it's like a wrapper for the setTimeout function. The documentation says that it provides exception handling. In addition, the documentation says I can cancel and flush a timeout.

Can someone please explain to me when an exception would happen with a timeout? I also don't understand why I need to flush a timeout. I would love an explanation or maybe a jsfiddle. For the life of me, I can't figure out why or even how to use these additional features.

Update: When I attempt to run the stop function, the catch handler associated with myTimer get's thrown. Here is my code:

var myTimer = null; 
$scope.hasStarted = false; 
$scope.start = function () { 
  if ($scope.hasStarted === false) { 
    $scope.isTimerActive = true; 
    myTimer = $timeout(function () { $scope.isTimerActive = false; }, 5000); 
    myTimer.catch(function (err) { 
      alert("An error happened with the clock."); 
    }); 
  }
} 

$scope.stopClock = function () { 
  $timeout.cancel(myTimer); 
  $scope.isClockActive = false; 
}  

Thank you!

1 Answer 1

12

$timeout is most awesome indeed.

Exception handling

$timeout returns a promise which can have an error state. For example

 var timePromise = $timeout(function(){ 
    throw new Error('I messed up');
 }, 10000);

 timePromise.catch(function(err){
    // do something with the error
 });

read all about promises here.


Cancel

Canceling a $timeout is easy. Instead of using clearTimeout you pass the promise back.

 var timePromise = $timeout(function(){
     // do thing
 }, 23432);

 // wait I didn't mean it!
 $timeout.cancel(timePromise);

Flush

Flush is most useful for unit testing, ultimately it fires any outstanding callbacks.

$timeout(function(){
   console.log('$timeout flush');
}, 222);

$timeout(function(){
   console.log('rocks my face');
}, 234232);

$timeout.flush(); // both console logs will fire right away!

or this file:

var itsDone = false;
$timeout(function(){
   itsDone = true;
}, 5000);

with this test:

// old no flush way (async)
it('should be done', function(done){
   expect(isDone).to.be.false;
   setTimeout(function(){
      expect(isDone).to.be.true;
      done();
   }, 5001);
});

// now with flush
it('should be done', function(){
   expect(isDone).to.be.false;
   $timeout.flush();
   expect(isDone).to.be.true;
});
Sign up to request clarification or add additional context in comments.

5 Comments

Thank you for your feedback. I've been playing with this, and I'm still having an issue. If I have one method in my controller that creates the timer, and another the stops the timer, an exception gets thrown. Why?
var myTimer = null; $scope.hasStarted = false; $scope.start = function () { if ($scope.hasStarted === false) { $scope.isTimerActive = true; myTimer = $timeout(function () { $scope.isTimerActive = false; }, 5000); myTimer.catch(function (err) { alert("An error happened with the clock."); }); }} $scope.stopClock = function () { $timeout.cancel(myTimer); $scope.isClockActive = false; }
I am confused, why did you post that code as a comment? What does it mean? Por que?
I updated the question to format code better. Essentially, I still don't understand the exception handling piece. Why would an exception get thrown if I try to cancel a timer that is running? Shouldn't it just get stopped?
It will be stopped. But lets say you wrote code that someone else is consuming. They may not know that the promise came from a timer. If that promise does not resolve it will catch, and an canceled timer will not resolve.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.