can-observation
Version:
Core observable indicators
155 lines (104 loc) • 4.76 kB
Markdown
{constructor} can-observation
can-observables
can-infrastructure
can-observation.prototype prototype
../package.json
Create observable values that derive their value from other observable
values.
`new Observation( fn [, context][, options] )`
Creates an observable value from the return value of the given function called with `this` as the `context`.
The following creates a `fullName` observation that derives its values from
the `person` observable.
```js
import Observation from "can-observation";
import observe from "can-observe";
const person = observe( { first: "Ramiya", last: "Meyer" } );
const fullName = new Observation( function() {
return person.first + " " + person.last;
} );
fullName.value; //-> "Ramiya Meyer";
fullName.on( function( newName ) {
newName; //-> "Bodhi Meyer"
} );
person.first = "Bodhi";
```
{function} fn The function whose value is being observed.
{Object} [context] What `this` should be when `fn` is called.
{Object} [options] An object that can configure the behavior of the
observation with the following properties:
- __priority__ `{Number}` - The priority this observation will be updated
within [can-queues].
- __isObservable__ `{Boolean}` - If reading this observable should call
[can-observation-recorder.add].
## Use Cases
`can-observation` is used to derive values from other values without
having to explicitly bind. This is used many places within CanJS:
- [can-define] `getters` that cache their value.
- [can-stache]'s live binding.
## Use
To use `can-observation`, import it and create an observation that
reads from other observables and returns a value.
The following creates a `fullName` observation that derives its values from
the `person` observable.
```js
import Observation from "can-observation";
import observe from "can-observe";
const person = observe( { first: "Ramiya", last: "Meyer" } );
var fullName = new Observation(function fullName(){
return person.first + " " + person.last;
});
fullName.value; //-> "Ramiya Meyer";
fullName.on( function( newName ) {
newName; //-> "Bodhi Meyer"
} );
person.first = "Bodhi";
```
Use [can-observation.prototype.off] to unbind.
## Debugging
#### Naming Functions
Observations [can-observation.prototype.can.getName name themselves] using the name of the
function passed to them. If you are using a `can-observation` directly, you should make sure the
function has a meaningful name.
This can be done by using [function declarations](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function) like:
```js
var fullName = new Observation(function fullName(){
return person.first + " " + person.last;
});
```
Instead of:
```js
var fullName = new Observation(function(){
return person.first + " " + person.last;
});
```
You can also name functions as follows:
```js
//!steal-remove-start
var fn = function(){ ... };
Object.defineProperty(fn, "name", {
value: "some meaningful name",
});
//!steal-remove-end
```
#### can-queues
If you use [can-queues] to debug, it's likely you'll see something like:
<pre>
NOTIFY running : Observation<fullName>.onDependencyChange ▶ { ... }
DERIVE running : Observation<fullName>.update ▶ { ... }
</pre>
These tasks are when an observation noticed a dependency has changed and when it began to update
its value. If you expand the task object (<code>▶ { ... }</code>), you should be able to see
exactly which dependency caused the observation to update.
## How it works
`can-observation` uses [can-event-queue/value/value] to implement its `.on`, `.off` methods and
call its internal `.onBound` and `.onUnbound` methods.
When bound for the first time, an observation calls its function between [can-observation-recorder]'s
[can-observation-recorder.start] and [can-observation-recorder.stop] to see what dependencies have been
bound. It then uses [recorder-dependency-helpers.js](http://canjs.github.io/can-observation/docs/recorder-dependency-helpers.html) to bind those dependencies to it's `dependencyChange` method.
When a dependency change happens, an observation adds its `.update` method to the __derive__ [can-queues].
When the `.update` happens, it repeats the process in the above paragraph, binding and unbind to whatever dependencies are
found with [can-observation-recorder.start] and [can-observation-recorder.stop].
[How it works: can-observation and can-observation-recorder](https://www.youtube.com/watch?v=UIhB-zXR5Yg)
covers how `can-observation` works.
<iframe width="560" height="315" src="https://www.youtube.com/embed/UIhB-zXR5Yg" frameborder="0" allowfullscreen></iframe>