d is global variable to access this library.
d itself is actually a function that wraps
d.run() for quick context set up and data retrieval. See
d.run() for more info.
Subscriptions are a connection between a path and multiple contexts. A subscription is created the first time it is requested and is then subscribed to each context that needs it.
d.subs.create() creates a new subscription at
data. If the subscription already exists, any new data replaces the existing. The created subscription will be attached to a queue that can be accessed later. This method does not subscribe data to any context, but sets up the methods to do so.
d.subs.find() turns a
path or subscription
id into a subscription. This is useful for subscription maintenance, including subscribing and unsubscribing from contexts.
d.subs.remove() completely removes a subscription from existence. All subscribed contexts are unsubscribed.
d.get() is a simple function that does many things. The first task of
d.get() is to retrieve data at
path is a string of parts separated by a
.. Each part refers a level of the data within
d.model. For example, a path like
_session.foo.bar would be resolved as
d.get() sets up a special starting path part
$. This path will always refer to the global model even when the context is scoped.
The second thing
d.get() does is set up the specified data as a subscription and subscribes it to the current context. Whenever a "change" to data is detected, the context will be rerun.
d.set(), on the other hand, sets data at
d.set() is dynamic enough to translate a string path into a series of models and collections so the right value is always set. This will also automatically resubscribe to any data if the subscription was changed.
d.reactive() takes a function
fn to be rerun any time a dependency changes. A dependency is simply any data returned from
fn will have
this pointing to the reactive context. It is given no arguments and expects no return value.
d.reactive() returns a "reactive context" which is simply a wrapper function for
fn. A reactive context must be called at least once to initiate its subscriptions.
A neat feature of contexts is their ability to be nested within each other. Any time a parent context is run, all children contexts are stopped and restarted. Reactive contexts can only be placed within a single parent context. If a context is run within a context that isn't it's parent, closing events will not be received and memory will leak.
The context also triggers events using Backbone's event API. These events include
Some notable properties of a reactive context include a globally unique id and a base path for scoping. A scoped context requires shorter paths to access the same data. For example, if there is a model at the path
Projects.1 and the context is scoped to it, any further paths will access the model directly. So
Project.1.title becomes just
title. Remember the global model can always be accessed with the path
Each context defines a
unsubscribe() method. These methods take a subscription and watch (or unwatch) for changes to data. Given the same arguments,
unsubscribe() should "undo" anything done by
subscribe(). Each subscription will only be subscribed to once.
Contexts also have a stop method that halts the context completely. All subscriptions are unsubscribed and the context is brought to a normalized state. A context can be restarted by calling it again.
Reactive contexts come with an easy clean up utility that helps to run some function whenever the context is stopped or re-run. This is useful for deep contexts that need to be destroyed regularly.
d.run() is the marriage of
d.reactive() in a simple package. If just a
path is given,
d.get() is used to retrieve the data and set up subscriptions. If
fn is given, a reactive context is created. If
fn is used with
path, the context is scoped to
d.depend() forces the current context to subscribe to
data. This allows contexts to subscribe to
data even if
data doesn't exist in
d.model. It creates a temporary subscription that is destroyed on context close. This method is hackable.
Several methods within this library are "hackable" and can be modified. This is useful for when core data needs to be controlled by something other than Backbone or context specific functionality is desired.
d.retrieve() is responsible for getting the value at path.
parts is an array of path partitions, always relative to
d.update() sets a
value at path. It also handles the firing of update events so reactive contexts can be rerun.
d.process() sets up subscriptions given a
value and path
parts. This should only create subscriptions, not subscribe them to any contexts. Even though this function will be rerun multiple times for the same subscriptions, the API will not duplicate subscriptions.
d.subscribe() is the default subscribe method used by subscriptions.
this within the method will refer to the subscription using it. By passing
fn, this method should set the proper events to call the context any time it needs to update.
d.unsubscribe() is the default unsubscribe method used by subscriptions. It is called in the same fashion as
d.subscribe(). Given the same arguments, it should completely reverse anything done by the subscribe method.
d.join() takes any number of string arguments and concats them together to form a path.
d._parts() takes a string
path and divides it into an array of path parts. Optionally pass
base to prefix it to path in the event
$ is not use.
d._keysplit() takes a string and separates it by
sep. You can use
sep in the path by prefixing it with
d._deep() gets or sets a
key deeply within an object. When setting a
key doesn't exist, objects are created to make it fit.
d._trim() normalizes a path by removing any leading or trailing separators.
obj as a Backbone model or collection. Useful in determining if data can take events or needs to be accessed in a different way.