KnockoutJS Computed Observables


Trying to understand how Knockouts auto-suscribe to observable´s dependencies… so far this is what i could get from the source code. So this is what happens when you declare a property as dependentObservable… e.g:  this.foo = ko.computed() :

  1. A function called “evaluateImmediate();” is called ( inside ko.dependentObservable: ko.computed is just an alias for dependentObservable)
  2. That function calls ko.dependencyDetection.begin() and assigns a callback as a parameter, which will be called each time any observable is called from now on.
  3. Now, the computed function is called… requesting the current value, just as an excuse to collect all dependencies inside the ko.dependencyDetection stack.
  4. Each time you “get” a value from an observable, this function is called: ko.dependencyDetection.registerDependency(observable); which serves to track all the dependencies after a ko.dependencyDetection.begin() was called… it it wasn´t called then that call is the ignored. So after point 3 was called, all the dependencies inside the computed property were collected and the computed property itself was registered as an observer of all the dependencies found, so next time you call a dependency, it will trigger it´s change to the computed observable to re-calculate it´s value.

It is a very smart technique. The key is in ko.dependencyDetection. Inside it has an array, which serves to keep a SCOPE of all the dependencies calls… so if you have nested computed observables, it will cascade down and resolve all the dependencies in order of how they get called. Very interesting.

So everytime you read an observable, ko.dependencyDetection.registerDependency() is fired, and if the code is “computing” a computed observable, then the call will be saved and used to register that observable to the computed observable who triggered the ko.dependencyDetection.begin()

The process would be something like this:

  1. You declare the computed property: this.COMP = ko.computed( function(){  return “Foo value is ” + this.foo(); } );
  2. KnockoutJS then calls that property ( same as doing this.COMP() ), so this.foo() get´s called internally.
  3. Because a computed property was called, when this.foo() gets called ko.dependencyDetection.registerDependency(…) will “save” that observable (this.foo) and suscribe this.COMP to this.foo´s changes.  ( Same as doing this.foo.suscribe(…) )
  4. Now, next time you change this.foo(“New value”) it will alert all it´s suscribers that it has a new value, and because the computed property got registered on it´s declaration, it will be  re-evaluated, and, because it´s an observable, it will trigger it´s change to it´s suscribers, if any.

Very very cool, i found this mechanism very interesting.

 

Advertisements