21

I was trying the code given in angularjs docs (given here: http://jsfiddle.net/zGqB8/) It just implements a time factory and uses $timeout to update the time object after each second.

angular.module('timeApp', [])
.factory('time', function($timeout) {
    var time = {};

    (function tick () {
        time.now = new Date().toString();
        $timeout(tick, 1000);  // how to do it using setInterval() ?
    })();

    return time;
});

How would I do it using setInterval() function instead of $timeout() ? I know that one need to use scope.$apply() to enter the angular execution context but how would that work in a factory function? I mean, in a controller, we have a scope, but we don't have scope in a factory function?

4
  • why do you need to use setInterval? This achieves the same results. Commented Jan 9, 2013 at 14:48
  • 4
    I like your current solution. Commented Jan 9, 2013 at 15:10
  • @LiviuT. yes, it works here but I just wanted to know how will I enter angular execution context when inside a factory function. Commented Jan 9, 2013 at 16:54
  • Angular now has $interval: docs.angularjs.org/api/ng/service/$interval Commented Jul 9, 2014 at 21:36

4 Answers 4

38

You can use $timeout as an interval.

var myIntervalFunction = function() {
    cancelRefresh = $timeout(function myFunction() {
        // do something
        cancelRefresh = $timeout(myIntervalFunction, 60000);
    },60000);
};

If the view is destroyed, you can destroy it with listening on $destroy:

$scope.$on('$destroy', function(e) {
        $timeout.cancel(cancelRefresh);
});
Sign up to request clarification or add additional context in comments.

7 Comments

I guess you misinterpreted the question. The setInterval() function of JS calls a function repetedly.
I know. At the moment there is no setInterval alternative in angular. The only way to simulate it is a $timeout function which calls itself recursively.
lets see how long it lasts before i start getting stackoverflow exceptions
@LeblancMeneses: there is no recursion here, so there won't be any stack overflow.
@TylerForsythe you're right, I've reverted a change which incorrectly renamed myFunction to myIntervalFunction. There is however no issue with a stack overflow as each $timeout is not a recursive call but rather defers the execution of the provided function which will be executed with a new call stack.
|
32

Update

Angular has implemented an $interval feature in version 1.2 - http://docs.angularjs.org/api/ng.$interval


Legacy example below, disregard unless you're using a version older than 1.2.

A setInterval implementation in Angular -

I've created a factory called timeFunctions, which exposes $setInterval and $clearInterval.

Note that any time I've needed to modify scope in a factory I've passed it in. I am unsure if this meets the "Angular way" of doing things, but it works well.

app.factory('timeFunctions', [

  "$timeout",

  function timeFunctions($timeout) {
    var _intervals = {}, _intervalUID = 1;

    return {

      $setInterval: function(operation, interval, $scope) {
        var _internalId = _intervalUID++;

        _intervals[ _internalId ] = $timeout(function intervalOperation(){
            operation( $scope || undefined );
            _intervals[ _internalId ] = $timeout(intervalOperation, interval);
        }, interval);

        return _internalId;
      },

      $clearInterval: function(id) {
        return $timeout.cancel( _intervals[ id ] );
      }
    }
  }
]);

Example Usage:

app.controller('myController', [

  '$scope', 'timeFunctions',

  function myController($scope, timeFunctions) {

    $scope.startFeature = function() {

      // scrollTimeout will store the unique ID for the $setInterval instance
      return $scope.scrollTimeout = timeFunctions.$setInterval(scroll, 5000, $scope);

      // Function called on interval with scope available
      function scroll($scope) {
        console.log('scroll', $scope);
        $scope.currentPage++;

      }
    },

    $scope.stopFeature = function() {
      return timeFunctions.$clearInterval( $scope.scrollTimeout );
    }

  }
]);

Comments

4

Could you call a normal JavaScript method and then within that method wrap the Angular code with an $apply?

Example

timer = setInterval('Repeater()', 50);

var Repeater = function () {
  // Get Angular scope from a known DOM element
  var scope = angular.element(document.getElementById(elem)).scope();
  scope.$apply(function () {
    scope.SomeOtherFunction();
  });
};

Comments

2

Latest release candidate (1.2.0 rc3) has interval support. See changelog

Comments

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.