| Of course! I love chatting about incremental computations and approaches in different frameworks :) You're getting warnings at devmode (i.e. during ng serve) that you've modified a binding after it was checked. This is not related to the way we trigger change detection. The simplest example is: @Component({
template: '{{ foo }}'
})
class AppComponent {
_foo = 0;
get foo() {
return this._foo++;
}
}
This is clearly unstable because every time we get the value of foo, we also increment _foo. What Angular does in devmode is to ensure developers are not hitting this issue.This is not related to setTimeout and the APIs we patch with zone.js. The check just safeguards us to not get into such cyclic binding scenarios. We'll be working on better explaining the error and the message in future releases. DOMElement is untouched, we only patch APIs so that we can plug into the microtask queue and trigger change detection when it's empty to ensure consistency between the model and the view. In fact, one of the projects high on our priority list is to make Zone.js optional and provide alternative, ergonomic APIs to trigger the change detection and specify local component state. I am saying ergonomic APIs because this is already possible, just not ideal since we have to specify a noop zone when bootstrapping the app. Optional, because many developers love the current behavior and we want to keep it available. And just, let me spent one more paragraph in explaining how the change detection works. Just want to show why is it that fast and with such a low memory overhead. Each component has a template that we translate to JavaScript instructions. For example: <span>{{ foo }}</span>
We will translate to something like (I'm writing the comment from my phone, some instruction names could be different in the CLI output): if (mode & creation) {
renderElement('span');
interpolation(ctx.foo);
} else if (mode & update) {
interpolation(ctx.foo);
}
That's a leaf component, but we can imagine how it works in more complicated hierarchies.So when we trigger change detection we just invoke the template functions for the components in update mode. We update only the bindings that have changed, without allocating any additional data structures to do that. Whether the framework is written to fit the language is mostly a subjective opinion. Angular doesn't go against the standard anywhere and does not introduce extra syntax on top of TypeScript. It also doesn't add new semantic to already existing constructs. In fact, to keep compliant is from a high priority to us. We constantly interact with different standardization bodies and keep up to date with standards. |
Yes, the basic template update mechanism is fine, and it does seem to be fast. I was talking more about the change detection, how it knows that foo has changed in the first place, particularly if it is a nested object or a getter that leads to one. I have had cases where Angular calls the getter constantly (proved by console.log).
I agree that there isn't another obvious way to figure out something changed, but that's the point - since JavaScript doesn't have a way to notify on changed properties, for the framework to make that the paradigm is an interesting choice. So it's great news that you're moving away from that and from zone.js.
This is where React's setState is much easier to reason about. I call a function, I know that I told React that something changed, so the update isn't a surprise. While setting a property does not usually cause anything to happen in Javascript, so I have trouble getting my head around how it works and what Angular is doing behind the scenes, and realizing that it must be polling, which isn't usually a good pattern.
> In fact, to keep compliant is from a high priority to us. We constantly interact with different standardization bodies and keep up to date with standards.
Which is definitely a good thing, but also an indication that it's not actually Javascript, just something that tries to be compatible with Javascript.
Anyway, thank you very much for responding! I also understand that Angular has a lot of history to work with and you're doing a good job with the paradigms you have.