Meteor has a simple dependency tracking system which allows it to
automatically rerun templates and other computations whenever
Session variables, database queries, and other data
Unlike most other systems, you don’t have to manually declare these dependencies — it “just works”. The mechanism is simple and efficient. When you call a function that supports reactive updates (such as a database query), it automatically saves the current Computation object, if any (representing, for example, the current template being rendered). Later, when the data changes, the function can “invalidate” the Computation, causing it to rerun (rerendering the template).
Applications will find
Tracker.autorun useful, while more
advanced facilities such as
callbacks are intended primarily for package authors implementing new
reactive data sources.
Run a function now and rerun it later whenever its dependencies change. Returns a Computation object that can be used to stop or observe the rerunning.
- runFunc Function
The function to run. It receives one argument: the Computation object that will be returned.
- onError Function
Optional. The function to run when an error happens in the Computation. The only argument it receives is the Error thrown. Defaults to the error being logged to the console.
Tracker.autorun allows you to run a function that depends on reactive data
sources, in such a way that if there are changes to the data later,
the function will be rerun.
For example, you can monitor a cursor (which is a reactive data source) and aggregate it into a session variable:
Or you can wait for a session variable to have a certain value, and do
something the first time it does, calling
stop on the computation to
prevent further rerunning:
The function is invoked immediately, at which point it may alert and
stop right away if
shouldAlert is already true. If not, the
function is run again when
shouldAlert becomes true.
A change to a data dependency does not cause an immediate rerun, but
rather “invalidates” the computation, causing it to rerun the next
time a flush occurs. A flush will occur automatically as soon as
the system is idle if there are invalidated computations. You can
Tracker.flush to cause an immediate flush of
all pending reruns.
If you nest calls to
Tracker.autorun, then when the outer call stops or
reruns, the inner call will stop automatically. Subscriptions and
observers are also automatically stopped when used as part of a
computation that is rerun, allowing new ones to be established. See
Meteor.subscribe for more information about
subscriptions and reactivity.
If the initial run of an autorun throws an exception, the computation is automatically stopped and won’t be rerun.
Process all reactive updates immediately and ensure that all invalidated computations are rerun.
Normally, when you make changes (like writing to the database), their impact (like updating the DOM) is delayed until the system is idle. This keeps things predictable — you can know that the DOM won’t go changing out from under your code as it runs. It’s also one of the things that makes Meteor fast.
Tracker.flush forces all of the pending reactive updates to complete.
For example, if an event handler changes a Session
variable that will cause part of the user interface to rerender, the
handler can call
flush to perform the rerender immediately and then
access the resulting DOM.
An automatic flush occurs whenever the system is idle which performs
exactly the same work as
Tracker.flush. The flushing process consists
of rerunning any invalidated computations. If additional
invalidations happen while flushing, they are processed as part of the
same flush until there is no more work to be done. Callbacks
Tracker.afterFlush are called
after processing outstanding invalidations.
It is illegal to call
flush from inside a
flush or from a running
The Tracker manual
describes the motivation for the flush cycle and the guarantees made by
Run a function without tracking dependencies.
- func Function
A function to call immediately.
Tracker.currentComputation temporarily set to
func‘s own return value. If
func accesses reactive data
sources, these data sources will never cause a rerun of the enclosing
True if there is a current computation, meaning that dependencies on reactive data sources will be tracked and potentially cause the current computation to be rerun.
This value is useful for data source implementations to determine whether they are being accessed reactively or not.
True if we are computing a computation now, either first time or recompute. This matches Tracker.active unless we are inside Tracker.nonreactive, which nullfies currentComputation even though an enclosing computation may still be running.
This value indicates, whether a flush is in progress or not.
The current computation, or
null if there isn't one. The current computation is the
Tracker.Computation object created by the innermost active call to
Tracker.autorun, and it's the computation that gains dependencies when reactive data sources are accessed.
It’s very rare to need to access
currentComputation directly. The
current computation is used implicitly by
Tracker.active (which tests whether there is one),
dependency.depend() (which registers that it depends on a
registers a callback with it).
Registers a new
onInvalidate callback on the current computation (which must exist), to be called immediately when the current computation is invalidated or stopped.
- callback Function
A callback function that will be invoked as
cis the computation on which the callback is registered.
.onInvalidate for more
Schedules a function to be called during the next flush, or later in the current flush if one is in progress, after all invalidated computations have been rerun. The function will be run once and not on subsequent flushes unless
afterFlush is called again.
- callback Function
A function to call at flush time.
Functions scheduled by multiple calls to
afterFlush are guaranteed
to run in the order that
afterFlush was called. Functions are
guaranteed to be called at a time when there are no invalidated
computations that need rerunning. This means that if an
function invalidates a computation, that computation will be rerun
before any other
afterFlush functions are called.
A Computation object represents code that is repeatedly rerun in
response to reactive data changes. Computations don’t have return
values; they just perform actions, such as rerendering a template on
the screen. Computations are created using
stop to prevent further rerunning of a
Each time a computation runs, it may access various reactive data sources that serve as inputs to the computation, which are called its dependencies. At some future time, one of these dependencies may trigger the computation to be rerun by invalidating it. When this happens, the dependencies are cleared, and the computation is scheduled to be rerun at flush time.
The current computation
Tracker.currentComputation) is the
computation that is currently being run or rerun (computed), and the
one that gains a dependency when a reactive data source is accessed.
Data sources are responsible for tracking these dependencies using
Invalidating a computation sets its
invalidated property to true
and immediately calls all of the computation’s
callbacks. When a flush occurs, if the computation has been invalidated
and not stopped, then the computation is rerun by setting the
invalidated property to
false and calling the original function
that was passed to
Tracker.autorun. A flush will occur when the current
code finishes running, or sooner if
Tracker.flush is called.
Stopping a computation invalidates it (if it is valid) for the purpose of calling callbacks, but ensures that it will never be rerun.
Prevents this computation from rerunning.
Stopping a computation is irreversible and guarantees that it will never be rerun. You can stop a computation at any time, including from the computation’s own run function. Stopping a computation that is already stopped has no effect.
Stopping a computation causes its
onInvalidate callbacks to run
immediately if it is not currently invalidated, as well as its
Nested computations are stopped automatically when their enclosing computation is rerun.
Invalidates this computation so that it will be rerun.
Invalidating a computation marks it to be rerun at
flush time, at
which point the computation becomes valid again. It is rare to
invalidate a computation manually, because reactive data sources
invalidate their calling computations when they change. Reactive data
sources in turn perform this invalidation using one or more
Invalidating a computation immediately calls all
callbacks registered on it. Invalidating a computation that is
currently invalidated or is stopped has no effect. A computation can
invalidate itself, but if it continues to do so indefinitely, the
result will be an infinite loop.
callback to run when this computation is next invalidated, or runs it immediately if the computation is already invalidated. The callback is run exactly once and not upon future invalidations unless
onInvalidate is called again after the computation becomes valid again.
- callback Function
Function to be called on invalidation. Receives one argument, the computation that was invalidated.
onInvalidate registers a one-time callback that either fires
immediately or as soon as the computation is next invalidated or
stopped. It is used by reactive data sources to clean up resources or
break dependencies when a computation is rerun or stopped.
To get a callback after a computation has been recomputed, you can
callback to run when this computation is stopped, or runs it immediately if the computation is already stopped. The callback is run after any
- callback Function
Function to be called on stop. Receives one argument, the computation that was stopped.
True if this computation has been stopped.
True if this computation has been invalidated (and not yet rerun), or if it has been stopped.
This property is initially false. It is set to true by
invalidate(). It is reset to false when the computation is
recomputed at flush time.
True during the initial run of the computation at the time
Tracker.autorun is called, and false on subsequent reruns and at other times.
This property is a convenience to support the common pattern where a computation has logic specific to the first run.
A Dependency represents an atomic unit of reactive data that a computation might depend on. Reactive data sources such as Session or Minimongo internally create different Dependency objects for different pieces of data, each of which may be depended on by multiple computations. When the data changes, the computations are invalidated.
Dependencies don’t store data, they just track the set of computations to invalidate if something changes. Typically, a data value will be accompanied by a Dependency object that tracks the computations that depend on it, as in this example:
This example implements a weather data source with a simple getter and
setter. The getter records that the current computation depends on
weatherDep dependency using
depend(), while the setter
signals the dependency to invalidate all dependent computations by
The reason Dependencies do not store data themselves is that it can be
useful to associate multiple Dependencies with the same piece of data.
For example, one Dependency might represent the result of a database
query, while another might represent just the number of documents in
the result. A Dependency could represent whether the weather is sunny
or not, or whether the temperature is above freezing.
Session.equals is implemented this way for
efficiency. When you call
Session.equals('weather', 'sunny'), the
current computation is made to depend on an internal Dependency that
does not change if the weather goes from, say,
Conceptually, the only two things a Dependency can do are gain a dependent and change.
A Dependency’s dependent computations are always valid (they have
invalidated === false). If a dependent is invalidated at any time,
either by the Dependency itself or some other way, it is immediately
See the Tracker manual
to learn how to create a reactive data source using
Invalidate all dependent computations immediately and remove them as dependents.
Declares that the current computation (or
fromComputation if given) depends on
dependency. The computation will be invalidated the next time
If there is no current computation and
depend() is called with no arguments, it does nothing and returns false.
Returns true if the computation is a new dependent of
dependency rather than an existing one.
- fromComputation Tracker.Computation
An optional computation declared to depend on
dependencyinstead of the current computation.
dep.depend() is used in reactive data source implementations to record
the fact that
dep is being accessed from the current computation.
True if this Dependency has one or more dependent Computations, which would be invalidated if this Dependency were to change.
For reactive data sources that create many internal Dependencies, this function is useful to determine whether a particular Dependency is still tracking any dependency relationships or if it can be cleaned up to save memory.