Defer evaluation on all computed properties in Knockout?
knockout.js
Solution
As you found out, normally, a `ko.computed` is calculated and dependencies are detected when the computed is first created.
When using `deferEvaluation`, dependency detection for a `ko.computed` is not performed immediately, but instead is performed each time the value is requested.
This provides a powerful mechanism for dynamically varying the dependencies, but does result in increased overhead.
Ryan talks about this a little on this page (scroll down to section 3 - The basic rules of computed observables):
Would it be possible to structure your code so that the `ko.computed` values are defined after the other properties are created?
If your main problem is in the dirty flag tracking, you could set up a beginInit() and endInit() methods in your base VM and set up your isDirty computed inside the endInit(). You or may not need the beginInit(), but it provides a nice hook for consistency and may be useful later on.
Of course, the derived VM needs to call the base init methods before and after setting up its observables. I'm not sure what your current strategy for creating the derived VM is - I'm typically use a factory to provide prototypal inheritance, and I have this sort of control over the initialization timing.
An simpler alternative to the beginInit() and endInit(), is to simply provide an initProperties() function in the derived classes where all the properties are defined, and call that method from the base VM, then set up your isDirty computed.
Problem
I am trying to make a base class for all my viewmodels so I for instance can check "isDirty" on the root-vm and have it check the entire tree of vms (while avoiding circular dependencies). When doing this I realized that the order of ko-properties is very important because a computed property set up its subscriptions based on what other properties exists at the time of creating the property. So if I would put a isDirty-computed like the one below in a base-class it would always initialize before the properties it depens on even exists. Anyway, to cut it short, I noticed I could use the deferEvaluation to remedy this problem. My question are: Are there any drawbacks of using deferEvaluation on all computed properties? Why is'nt this behaviour true by default? When would I need it set to false? Can I do this isDirty-property better? Any suggestions on improving it or doing it in some other way? And alternatively, is there any way to explicitly disable initialization of computed properties until the entire object with all its properties is created, and then run it in some way. I mean the only problem for me is that the subscriptions are set up before all properties are in place. Note: I'm using KO Lite Tools for dirty-tracking ``` function ViewModel() { var self = this; self.isDirty = ko.computed(function () { for (var p in self) { if (self[p].isDirty) { if (self[p].isDirty()) return true; } else if (self[p].subscribe && self[p].push) { // assuming ko.observableArray for (var i = 0, j = self[p]().length; i < j; i++) { if (self[p]()[i].isDirty) { if (self[p]()[i].isDirty()) return true; } } } } return false; }, this, { deferEvaluation: true }); } ``` Note: Just noticed that this code will fail if I have another computed property that is depending on isDirty. This was kind of expected but also unfortunate. It would be great if I instead could delay and force all subscriptions to after object creation.