mirror of
https://github.com/zhigang1992/angular.js.git
synced 2026-06-19 06:36:15 +08:00
perf(Scope): remove the need for the extra watch in $watchGroup
Instead of using a counter and an extra watch, just schedule the reaction function via $evalAsync. This gives us the same/similar ordering and coalecsing of updates as counter without the extra overhead. Also the code is easier to read. Since interpolation uses watchGroup, this change additionally improves performance of interpolation. In large table benchmark digest cost went down by 15-20% for interpolation. Closes #8396
This commit is contained in:
@@ -393,9 +393,9 @@ function $RootScopeProvider(){
|
||||
var oldValues = new Array(watchExpressions.length);
|
||||
var newValues = new Array(watchExpressions.length);
|
||||
var deregisterFns = [];
|
||||
var changeCount = 0;
|
||||
var self = this;
|
||||
var masterUnwatch;
|
||||
var changeReactionScheduled = false;
|
||||
var firstRun = true;
|
||||
|
||||
if (watchExpressions.length === 1) {
|
||||
// Special case size of one
|
||||
@@ -407,29 +407,31 @@ function $RootScopeProvider(){
|
||||
}
|
||||
|
||||
forEach(watchExpressions, function (expr, i) {
|
||||
var unwatch = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
|
||||
var unwatchFn = self.$watch(expr, function watchGroupSubAction(value, oldValue) {
|
||||
newValues[i] = value;
|
||||
oldValues[i] = oldValue;
|
||||
changeCount++;
|
||||
}, false, function watchGroupDeregNotifier() {
|
||||
arrayRemove(deregisterFns, unwatch);
|
||||
if (!deregisterFns.length) {
|
||||
masterUnwatch();
|
||||
if (!changeReactionScheduled) {
|
||||
changeReactionScheduled = true;
|
||||
self.$evalAsync(watchGroupAction);
|
||||
}
|
||||
});
|
||||
|
||||
deregisterFns.push(unwatch);
|
||||
}, this);
|
||||
|
||||
masterUnwatch = self.$watch(function watchGroupChangeWatch() {
|
||||
return changeCount;
|
||||
}, function watchGroupChangeAction(value, oldValue) {
|
||||
listener(newValues, (value === oldValue) ? newValues : oldValues, self);
|
||||
deregisterFns.push(unwatchFn);
|
||||
});
|
||||
|
||||
function watchGroupAction() {
|
||||
changeReactionScheduled = false;
|
||||
|
||||
if (firstRun) {
|
||||
firstRun = false;
|
||||
listener(newValues, newValues, self);
|
||||
} else {
|
||||
listener(newValues, oldValues, self);
|
||||
}
|
||||
}
|
||||
|
||||
return function deregisterWatchGroup() {
|
||||
while (deregisterFns.length) {
|
||||
deregisterFns[0]();
|
||||
deregisterFns.shift()();
|
||||
}
|
||||
};
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user