diff options
| author | Julie | 2013-09-13 12:47:05 -0700 |
|---|---|---|
| committer | Vojta Jina | 2013-10-07 13:45:40 -0700 |
| commit | 2b5ce84fca7b41fca24707e163ec6af84bc12e83 (patch) | |
| tree | d3fbcfd3c7e2e62fe60df6faa9823abda57b9bd7 /src/ng/interval.js | |
| parent | a80e96cea184b392505f0a292785a5c66d45e165 (diff) | |
| download | angular.js-2b5ce84fca7b41fca24707e163ec6af84bc12e83.tar.bz2 | |
feat($interval): add a service wrapping setInterval
The $interval service simplifies creating and testing recurring tasks.
This service does not increment $browser's outstanding request count,
which means that scenario tests and Protractor tests will not timeout
when a site uses a polling function registered by $interval. Provides
a workaround for #2402.
For unit tests, repeated tasks can be controlled using ngMock$interval's
tick(), tickNext(), and tickAll() functions.
Diffstat (limited to 'src/ng/interval.js')
| -rw-r--r-- | src/ng/interval.js | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/ng/interval.js b/src/ng/interval.js new file mode 100644 index 00000000..e612f3e4 --- /dev/null +++ b/src/ng/interval.js @@ -0,0 +1,90 @@ +'use strict'; + + +function $IntervalProvider() { + this.$get = ['$rootScope', '$window', '$q', + function($rootScope, $window, $q) { + var intervals = {}; + + + /** + * @ngdoc function + * @name ng.$interval + * + * @description + * Angular's wrapper for `window.setInterval`. The `fn` function is executed every `delay` + * milliseconds. + * + * The return value of registering an interval function is a promise. This promise will be + * notified upon each tick of the interval, and will be resolved after `count` iterations, or + * run indefinitely if `count` is not defined. The value of the notification will be the + * number of iterations that have run. + * To cancel an interval, call `$interval.cancel(promise)`. + * + * In tests you can use {@link ngMock.$interval#flush `$interval.flush(millis)`} to + * move forward by `millis` milliseconds and trigger any functions scheduled to run in that + * time. + * + * @param {function()} fn A function that should be called repeatedly. + * @param {number} delay Number of milliseconds between each function call. + * @param {number=} [count=0] Number of times to repeat. If not set, or 0, will repeat + * indefinitely. + * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise + * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. + * @returns {promise} A promise which will be notified on each iteration. + */ + function interval(fn, delay, count, invokeApply) { + var setInterval = $window.setInterval, + clearInterval = $window.clearInterval; + + var deferred = $q.defer(), + promise = deferred.promise, + count = (isDefined(count)) ? count : 0, + iteration = 0, + skipApply = (isDefined(invokeApply) && !invokeApply); + + promise.then(null, null, fn); + + promise.$$intervalId = setInterval(function tick() { + deferred.notify(iteration++); + + if (count > 0 && iteration >= count) { + deferred.resolve(iteration); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + } + + if (!skipApply) $rootScope.$apply(); + + }, delay); + + intervals[promise.$$intervalId] = deferred; + + return promise; + } + + + /** + * @ngdoc function + * @name ng.$interval#cancel + * @methodOf ng.$interval + * + * @description + * Cancels a task associated with the `promise`. + * + * @param {number} promise Promise returned by the `$interval` function. + * @returns {boolean} Returns `true` if the task was successfully canceled. + */ + interval.cancel = function(promise) { + if (promise && promise.$$intervalId in intervals) { + intervals[promise.$$intervalId].reject('canceled'); + clearInterval(promise.$$intervalId); + delete intervals[promise.$$intervalId]; + return true; + } + return false; + }; + + return interval; + }]; +} |
