diff --git a/src/ng/interval.js b/src/ng/interval.js index 909855bff5ba..d3922a96f02e 100644 --- a/src/ng/interval.js +++ b/src/ng/interval.js @@ -138,6 +138,7 @@ function $IntervalProvider() { iteration = 0, skipApply = (isDefined(invokeApply) && !invokeApply); + deferred.$$skipApply = skipApply; count = isDefined(count) ? count : 0; promise.then(null, null, fn); diff --git a/src/ng/q.js b/src/ng/q.js index 4ac55423e6e8..b6e9b3fb7a41 100644 --- a/src/ng/q.js +++ b/src/ng/q.js @@ -171,8 +171,8 @@ function $QProvider() { this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { - return qFactory(function(callback) { - $rootScope.$evalAsync(callback); + return qFactory(function(callback, skipApply) { + $rootScope.$evalAsync(callback, skipApply); }, $exceptionHandler); }]; } @@ -208,7 +208,7 @@ function qFactory(nextTick, exceptionHandler) { if (pending) { var callbacks = pending; pending = undefined; - value = ref(val); + value = ref(val, deferred.$$skipApply); if (callbacks.length) { nextTick(function() { @@ -217,7 +217,7 @@ function qFactory(nextTick, exceptionHandler) { callback = callbacks[i]; value.then(callback[0], callback[1], callback[2]); } - }); + }, deferred.$$skipApply); } } }, @@ -239,7 +239,7 @@ function qFactory(nextTick, exceptionHandler) { callback = callbacks[i]; callback[2](progress); } - }); + }, deferred.$$skipApply); } } }, @@ -331,14 +331,14 @@ function qFactory(nextTick, exceptionHandler) { }; - var ref = function(value) { + var ref = function(value, skipApply) { if (value && isFunction(value.then)) return value; return { then: function(callback) { var result = defer(); nextTick(function() { result.resolve(callback(value)); - }); + }, skipApply); return result.promise; } }; diff --git a/src/ng/rootScope.js b/src/ng/rootScope.js index 25a78ebabe02..e636addf86df 100644 --- a/src/ng/rootScope.js +++ b/src/ng/rootScope.js @@ -904,18 +904,35 @@ function $RootScopeProvider(){ * - `function(scope)`: execute the function with the current `scope` parameter. * */ - $evalAsync: function(expr) { + $evalAsync: function(expr, skipApply) { // if we are outside of an $digest loop and this is the first time we are scheduling async // task also schedule async auto-flush - if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) { - $browser.defer(function() { - if ($rootScope.$$asyncQueue.length) { - $rootScope.$digest(); - } - }); + if (!skipApply) { + if (!$rootScope.$$phase && !$rootScope.$$asyncQueue.length) { + $browser.defer(function() { + if ($rootScope.$$asyncQueue.length) { + $rootScope.$digest(); + } + }); + } + this.$$asyncQueue.push({scope: this, expression: expr}); + } else { + var asyncQueue = ($rootScope.$$liteAsyncQueue || ($rootScope.$$liteAsyncQueue = [])); + var asyncTask; + if (!asyncQueue.length) { + $browser.defer(function() { + while (asyncQueue.length) { + try { + asyncTask = asyncQueue.shift(); + asyncTask.scope.$eval(asyncTask.expression); + } catch (e) { + $exceptionHandler(e); + } + } + }); + } + asyncQueue.push({scope: this, expression: expr}); } - - this.$$asyncQueue.push({scope: this, expression: expr}); }, $$postDigest : function(fn) { diff --git a/test/ng/intervalSpec.js b/test/ng/intervalSpec.js index 0d101246ebf7..8d6503f44522 100644 --- a/test/ng/intervalSpec.js +++ b/test/ng/intervalSpec.js @@ -98,6 +98,21 @@ describe('$interval', function() { })); + it('should NOT call $rootScope.$digest if invokeApply is set to false', + inject(function($interval, $rootScope, $window, $browser) { + var digestSpy = spyOn($rootScope, '$digest').andCallThrough(); + var resolveSpy = jasmine.createSpy('resolve'); + var notifySpy = jasmine.createSpy('notify'); + $interval(noop, 1000, 1, false).then(resolveSpy, null, notifySpy); + + $window.flush(4000); + $browser.defer.flush(); + expect(digestSpy).not.toHaveBeenCalled(); + expect(resolveSpy).toHaveBeenCalledOnce(); + expect(notifySpy).toHaveBeenCalledOnce(); + })); + + it('should allow you to specify the delay time', inject(function($interval, $window) { var counter = 0; $interval(function() { counter++; }, 123);