3

I'm having an issue understanding how the promise returned by $interval works in Angular.

Let's say in the following example, we have a simple "api" factory with a method called "getStuff" that returns an array with one item. We also have a controller that calls $timeout on that factory:

angular.module("app",[])
  .factory('api', function(){
    return {
      getStuff: function() {      
        return ["stuff"];
      } 
    };   
  })
  .controller('appCtrl', function($scope, $timeout, api){
    $timeout(api.getStuff, 1000)
      .then(function(response){
        console.log(response);
      });
  })

This will log '["stuff"]' in the console after 1 second, which is great.

So lets say I want to call that method every second by replacing $timeout with $interval. Now nothing happens:

angular.module("app",[])
  .factory('api', function(){
    return {
      getStuff: function() {      
        return ["stuff"];
      } 
    };   
  })
  .controller('appCtrl', function($scope, $interval, api){
    $interval(api.getStuff, 1000)
      .then(function(response){
        console.log(response);
      });
  })

What is different between $timeout and $interval in this case?

I appreciate all help!

bince
  • 1,941
  • 2
  • 13
  • 8

2 Answers2

8

Added the count value to the example that the DIMM Reaper's provided in a comment to Christophe L's answer:

var app = angular.module("app", []);

app.run(function ($interval) {
    console.log('This fiddle will self destruct...');
    
    var timer = $interval(function (count) {
        console.log('tick... ' + count);
    }, 500, 4, false);
    
    timer.then(function(res) {
        console.log("BOOM! " + res);
    });
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.8/angular.min.js"></script>

<body ng-app="app">
</body>

Output:

This fiddle will self destruct...
tick... 1
tick... 2
tick... 3
tick... 4
BOOM! 4

The final result is the final count.

Sámal Rasmussen
  • 2,887
  • 35
  • 36
4

The only thing you can do with the promise returned by $interval is cancel it (to stop its execution):

var handle = $interval(someFunc, 1000);
...
$interval.cancel(handle);

Your code should probably look like:

app.controller('appCtrl', function($scope, $interval, api) {
    $interval(function() {
        console.log(api.getStuff());
    }, 1000);
});

To be fancy and see everything working together:

app.controller('appCtrl', function($scope, $interval, $timeout, api) {
    var handle = $interval(function() {
        console.log(api.getStuff());
    }, 1000);

    $timeout(function() {
        $interval.cancel(handle);
    }, 5000);
});
Christophe L
  • 13,725
  • 6
  • 33
  • 33
  • 3
    I disagree with your first point that the promise returned by `$interval` can only be used to cancel the timer. It's a full-fledged promise: it gets resolved when the timer expires (assuming you set a max time) and it gets rejected when you call `$interval.cancel()`. [Here's a fiddle](http://jsfiddle.net/dimmreaper/a6u80jvn/). – The DIMM Reaper May 18 '15 at 16:47