Skip to content
This repository has been archived by the owner on Apr 12, 2024. It is now read-only.

$interval invokes $rootScope.$digest() regardless of invokeApply param #7103

Closed
wmadden opened this issue Apr 13, 2014 · 2 comments
Closed

Comments

@wmadden
Copy link

wmadden commented Apr 13, 2014

$interval() uses a $q deferred to notify its callback function each tick and the $QProvider wraps all callbacks in $rootScope.$evalAsync which executes them inside the next $digest loop.

This means that the final line of $interval has no useful effect:

if (!skipApply) $rootScope.$apply();

and the invokeApply param is very misleading since regardless of what value it holds $interval will cause a full $rootScope.$digest() with every invocation.

It might be better to have $interval and $timeout functions available on a $scope instance so that a) they get cleaned up when the scope is destroyed, b) they only cause their $scope instance to be dirty checked.

@lefos987 lefos987 added this to the Backlog milestone Apr 14, 2014
@erwinmombay
Copy link

+1, even with the skipApply option set to false the still causes digest cause of the evalAsync

@n8agrin
Copy link

n8agrin commented Jun 25, 2014

We noticed this as well when trying to understand why any $interval use triggered a digest loop, making it unusable for us.

caitp added a commit to caitp/angular.js that referenced this issue Jun 25, 2014
This CL allows $q Deferred objects to avoid invoking $rootScope.$digest, by optionally adding
asynchronously invoked functions to a different queue which is processed outside of $digest.

Closes angular#7103
@caitp caitp closed this as completed in 19b6b34 Jun 27, 2014
ckknight pushed a commit to ckknight/angular.js that referenced this issue Jul 16, 2014
$evalAsync triggers a digest, and is unsuitable when it is expected that a digest should not occur.

BREAKING CHANGE

Previously, even if invokeApply was set to false, a $rootScope digest would occur during promise
resolution. This is no longer the case, as promises returned from $timeout and $interval will no
longer trigger $evalAsync (which in turn causes a $digest) if `invokeApply` is false.

Workarounds include manually triggering $scope.$apply(), or returning $q.defer().promise from a
promise callback, and resolving or rejecting it when appropriate.

    var interval = $interval(function() {
      if (someRequirementFulfilled) {
        $interval.cancel(interval);
        $scope.$apply();
      }
    }, 100, 0, false);

or:

    var interval = $interval(function (idx) {
      // make the magic happen
    }, 1000, 10, false);
    interval.then(function(idx) {
      var deferred = $q.defer();
      // do the asynchronous magic --- $evalAsync will cause a digest and cause
      // bindings to update.
      return deferred.promise;
    });

Closes angular#7999
Closes angular#7103
thatmarvin pushed a commit to thatmarvin/ng-idle that referenced this issue Aug 5, 2014
fires. The invokeApply param is effectively ignored in 1.2.x so this
patch doesn't do anything there.

See angular/angular.js#7103 for more details
on the fix that landed in 1.3.x.
thatmarvin pushed a commit to thatmarvin/ng-idle that referenced this issue Aug 5, 2014
This prevents excessive $digest cycles whenever the $interval callback
fires. The invokeApply param is effectively ignored in 1.2.x so this
patch doesn't do anything there.

See angular/angular.js#7103 for more details
on the fix that landed in 1.3.x.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants