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

Commit 4e15c4f

Browse files
matskomhevery
authored andcommitted
chore($rootScope): provide support to execute a function after the digest cycle is complete
1 parent 4382df0 commit 4e15c4f

File tree

2 files changed

+90
-0
lines changed

2 files changed

+90
-0
lines changed

src/ng/rootScope.js

+16
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ function $RootScopeProvider(){
119119
this['this'] = this.$root = this;
120120
this.$$destroyed = false;
121121
this.$$asyncQueue = [];
122+
this.$$postDigestQueue = [];
122123
this.$$listeners = {};
123124
this.$$isolateBindings = {};
124125
}
@@ -133,6 +134,7 @@ function $RootScopeProvider(){
133134

134135

135136
Scope.prototype = {
137+
constructor: Scope,
136138
/**
137139
* @ngdoc function
138140
* @name ng.$rootScope.Scope#$new
@@ -167,6 +169,7 @@ function $RootScopeProvider(){
167169
child.$root = this.$root;
168170
// ensure that there is just one async queue per $rootScope and it's children
169171
child.$$asyncQueue = this.$$asyncQueue;
172+
child.$$postDigestQueue = this.$$postDigestQueue;
170173
} else {
171174
Child = function() {}; // should be anonymous; This is so that when the minifier munges
172175
// the name it does not become random set of chars. These will then show up as class
@@ -494,6 +497,7 @@ function $RootScopeProvider(){
494497
var watch, value, last,
495498
watchers,
496499
asyncQueue = this.$$asyncQueue,
500+
postDigestQueue = this.$$postDigestQueue,
497501
length,
498502
dirty, ttl = TTL,
499503
next, current, target = this,
@@ -566,6 +570,14 @@ function $RootScopeProvider(){
566570
} while (dirty || asyncQueue.length);
567571

568572
clearPhase();
573+
574+
while(postDigestQueue.length) {
575+
try {
576+
postDigestQueue.shift()();
577+
} catch (e) {
578+
$exceptionHandler(e);
579+
}
580+
}
569581
},
570582

571583

@@ -696,6 +708,10 @@ function $RootScopeProvider(){
696708
this.$$asyncQueue.push(expr);
697709
},
698710

711+
$$postDigest : function(expr) {
712+
this.$$postDigestQueue.push(expr);
713+
},
714+
699715
/**
700716
* @ngdoc function
701717
* @name ng.$rootScope.Scope#$apply

test/ng/rootScopeSpec.js

+74
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ describe('Scope', function() {
1212
}));
1313

1414

15+
it('should expose the constructor', inject(function($rootScope) {
16+
if (msie) return;
17+
expect($rootScope.__proto__).toBe($rootScope.constructor.prototype);
18+
}));
19+
20+
1521
it('should not have $root on children, but should inherit', inject(function($rootScope) {
1622
var child = $rootScope.$new();
1723
expect(child.$root).toEqual($rootScope);
@@ -672,6 +678,74 @@ describe('Scope', function() {
672678
expect(log).toEqual('parent.async;child.async;parent.$digest;child.$digest;');
673679
}));
674680

681+
it('should not run another digest for an $$postDigest call', inject(function($rootScope) {
682+
var internalWatchCount = 0;
683+
var externalWatchCount = 0;
684+
685+
$rootScope.internalCount = 0;
686+
$rootScope.externalCount = 0;
687+
688+
$rootScope.$evalAsync(function(scope) {
689+
$rootScope.internalCount++;
690+
});
691+
692+
$rootScope.$$postDigest(function(scope) {
693+
$rootScope.externalCount++;
694+
});
695+
696+
$rootScope.$watch('internalCount', function(value) {
697+
internalWatchCount = value;
698+
});
699+
$rootScope.$watch('externalCount', function(value) {
700+
externalWatchCount = value;
701+
});
702+
703+
$rootScope.$digest();
704+
705+
expect(internalWatchCount).toEqual(1);
706+
expect(externalWatchCount).toEqual(0);
707+
}));
708+
709+
it('should run a $$postDigest call on all child scopes when a parent scope is digested', inject(function($rootScope) {
710+
var parent = $rootScope.$new(),
711+
child = parent.$new(),
712+
count = 0;
713+
714+
$rootScope.$$postDigest(function() {
715+
count++;
716+
});
717+
718+
parent.$$postDigest(function() {
719+
count++;
720+
});
721+
722+
child.$$postDigest(function() {
723+
count++;
724+
});
725+
726+
expect(count).toBe(0);
727+
$rootScope.$digest();
728+
expect(count).toBe(3);
729+
}));
730+
731+
it('should run a $$postDigest call even if the child scope is isolated', inject(function($rootScope) {
732+
var parent = $rootScope.$new(),
733+
child = parent.$new(true),
734+
signature = '';
735+
736+
parent.$$postDigest(function() {
737+
signature += 'A';
738+
});
739+
740+
child.$$postDigest(function() {
741+
signature += 'B';
742+
});
743+
744+
expect(signature).toBe('');
745+
$rootScope.$digest();
746+
expect(signature).toBe('AB');
747+
}));
748+
675749
it('should cause a $digest rerun', inject(function($rootScope) {
676750
$rootScope.log = '';
677751
$rootScope.value = 0;

0 commit comments

Comments
 (0)