We were unable to load Disqus. If you are a moderator please see our troubleshooting guide.
I've got 'a thing' whereby I only believe that I understand something if I am able to explain it in simpler language than I learnt it. I think this is my inner mentor, which feels it's not worth knowing something if that knowledge can't be passed on. I don't want to detract from your excellent technical explanation, but may I put my own simplistic spin on things...
My code works within the domain of KO. I provide the workings of my computed, but KO controls when my code executes. KO is also in the priviledged position to know when any observable is being observed. The dependency tracker is somewhat like a macro recorder in other applications. Before my computed code body executes, the middle man starts recording. It keeps a list of observations made during that execution (using a stack to support nested computeds) and stops recording after my code has completed. KO easily encapsulates the function that I provided and monitors observations while it runs.
Raith - I like your rewording of the explanation. For things like this, it is helpful to have several ways to explain it.
Thanks Ryan; I have heard lots of explanations of Angular's Dirty Checking, and Dependency Injection systems and I was curious how Knockout handled it. Having experience with both, I knew that Knockout was a much less error prone system, and now I know why. It's much easier to understand how Knockout computeds work than it is to understand the digest cycle in Angular.
Great post - do you know of any good comparisons made of the scalability/speed of Knockout and Angular.
hi @ryan, knockout-amd-helpers is not working for me. I've downloaded the master branch as zip from github. When I open the index-require.html in the browser I get Cross origin requests are only supported for HTTP, is there something I"m doing wrong or not doing to use this?
Hisakazu Ishibashi - you would need to host the files on a static web server, as opening them as local files will cause those errors. I don't know what technology that you use the most, but something like this: https://github.com/nodeapps... works well enough. Hope that helps!
Hi again Ryan Niemeyer
First of all, I was reading http://www.knockmeout.net/2... when I wrote my comment. I don't know how Disqus got me to this article.
Second, I had the hope I could use the knockout-amd-helpers for a Ko+jquery.mobile+phonegap SPA. My current index is already a mess only with 3 pages. I'm using requirejs and I'm looking for some sort of module I could use to separate my JQM pages in different files.
Anyway, thanks for the quick response.
Thanks for a great explanation, every now and then the question popped up in the back of my mind...
To make sure I understand correctly though, is a dependency detected even if it is not called the first time the computed is evaluated?
For example, with this computed:
o1 = ko.observable(false);
value = ko.pureComputed(function() {
return o1() ? o2() : undefined;
}
... will changes to o2 cause notifications once o1 has been set to true?
@Franck - each time that the computed is evaluated it re-considers its dependencies. So, if o1() is initially false, only o1 would be a dependency. When it flips to true, then both o1 and o2 would be dependencies.
So... I wrote the test, and as expected given your explanations the dependencies are updated every time the computed observable is recomputed. Something however must trigger the recomputation - and I have been bitten by not understanding that in the past: in the example below updating o1 does create a new dependency on o2, but setting guard to true does not create a dependency on o3:
var o1 = ko.observable(false).logIt('o1');
var o2 = ko.observable(1).logIt('o2');
var o3 = ko.observable(1).logIt('o3');
var guard = false;
var comp = ko.pureComputed(function() {
var result = {};
if (o1()) {
result['o2'] = o2();
}
if (guard) {
result['guard'] = o3();
}
return result;
}).logIt('computed');
o2(2); -> comp doesn't trigger
o1(true);
o2(3); -> comp does trigger
guard = true;
o3(2); -> comp does *not* trigger
Much more obvious once you understand how knockout works...
Ryan, this is incredibly well explained. Thank you very much for sharing your knowledge of this great tool. My previous brushes with data binding left me cold (asp.net web forms) and it took Knockout to really open my eyes to the possibilities when applied as an MVVM solution. As useful and enjoyable as KO is to use, what really excited me was the complex internal workings that make the dependency tracking work. Your article has given me a real boost and I am definitely going to investigate the 'middle man' further. Thanks again :-)