-
Notifications
You must be signed in to change notification settings - Fork 27.4k
Optimize $watch and $parse for frozen/immutable objects #6391
Comments
If you $watch a constant expression, angular will automatically remove the watch after the first listener is called. angular.js/src/ng/rootScope.js Lines 336 to 342 in f7d28cd
|
What I am proposing is more general and I think it could solve the "can't have > 2000 $watch expressions" issue. $parse detects constants, but will not detect immutable data. What I am proposing is sort of the dynamic version of the constant detection that $parse does.
In this example, for each of the persons, their $scope, and $scope.p, and $scope.p.name are all immutable. This can be detected by looking first at $scope.isFrozen(). If that fails, then look no further. But when they are all frozen, the expression can be evaluated exactly like the constant expressions from $parse. Thus the $watch can be removed. There is a middle road also. When $scope.isFrozen() == true, then the function that evaluates the expression can directly bind p in its closure. When later p.isFrozen() == true, then the function that evaluates the expression can directly bind the name object in its closure. This leads to more efficient evaluation (although there is a slight cost, so there is a trade-off). This is not possible to do simply by $parse, because the immutability information can only be known by accessing the scope, and $parse does not know about scopes. Therefore you can think of it as a more dynamic constant detector than the one $parse knows. I also believe that this immutability detector can be pretty useful in a lot of real-life situations. $parse fails at this point: A field lookup is a primary, so at this point the primary.constant == false. Line 444 in f7d28cd
|
So what you're saying is that this is a duplicate issue of all of the bindonce stuff :p I think you might want to take a look at and perhaps comment on the discussions in the angular 2.0 drafts: https://docs.google.com/document/d/1f5VWROeTI2kJwVKbNsrHuEz5IqtZe14OpoxM9fEYJNU/edit#heading=h.6rzfundz70u6 |
I think this is more powerful than bind-once, and less complex than namespaces. I've added a few comments to the design doc. Using immutable data instead of bind-sometimes is good engineering. Triggers that only sometimes fire cause lots of complexity. However, declaring data to be immutable does not introduce any compleity at all. Rather, it reduces complexity by giving the system stronger invariants. So this is a rare win/win change I think. In this proposal the programmer exactly expresses his intent at one place, by indicating that a given object is immutable. Thus there is no API change at all in Angular. The I will note that I haven't spent a lot of time thinking about this, but having hacked Haskell for some time, this problem screams 'take advantage of immutable data!', and since ES5 has some support for it, it should be used. |
Any work on this? |
I see a lot of people having problems with too many $watch expressions. I have seen solutions such as bindonce, but that solution brings a lot of complexity on its own.
I suggest that AngularJS integrates and encourage a separation between mutable and immutable data, and detect frozen objects in $watch expressions. This has testability, complexity and speed advantages.
No new APIs or syntax is required for this.
Immutable data in Ecmascript 5.1 can be created using Object.freeze(). When a $watch expression is evaluated, and all constituent objects are frozen, then the result of the expression is a constant.
Current vs new watch expressions:
Of course, the invariant can be part of the
f
function as well by integrating it into the current$parse
.For all current code, this only adds a simple test for scope.isFrozen in the evaluation function, but it opens up for much more performant UIs by having watches that automatically learn about immutable data.
The onConstant callback can be used to remote a $watch from the digest cycle. Thus properly designed programs would be able to have thousands of $watches as long as they use immutable data to back them.
The text was updated successfully, but these errors were encountered: