The Tracker methods don't exactly belong to the core of Meteor's functionality, are seldomly used in tutorials and beginner books (and if they are they are not explained very well), and as a consequence are considered a lot more "scary" than most of the rest of the framework.
I, for one, have never managed to wrangle Tracker.autorun
into a project of mine as it never seems to do what is expected of it. This is what the docs say it does:
Run a function now and rerun it later whenever its dependencies change.
To me this sounds like a way of making non-reactionary sources reactionary, but then you come to the examples, the first of which looks like this:
Tracker.autorun(function () { var oldest = _.max(Monkeys.find().fetch(), function (monkey) { return monkey.age; }); if (oldest) Session.set("oldest", oldest.name); });
How exactly is this different from not using Tracker.autorun
? Cursors are already a reactionary source, and to make matters more confusing the next example deals with another reactionary source: Sessions.
Does Tracker.autorun
only work with reactionary sources, and if so what is the benefit of using them inside a Tracker
? Making them doubly reactionary?
To implement reactive programming (a variant of event driven programming), Meteor uses 2 different concepts :
These two concepts are implemented by two rarely used underlying Tracker
objects, namely Tracker.Computation and the helper object Tracker.Dependency which is a container for storing a set of computations.
A Tracker.Computation
is an object with 2 important methods :
invalidate()
, which is causing the computation to rerun.onInvalidate(callback)
for actually running the computation arbitrary code.When you call Tracker.autorun
, you're basically creating a new computation and registering an onInvalidate
callback with the function you pass as argument.
A Tracker.Dependency
is a collection of computations with 2 methods.
depend()
: adds the current computation to the set.changed()
: when called, invalidates every registered computations.When a reactive data source registers a dependency inside a computation, it is calling Dependency.depend()
, which simply adds the current computation (if any) to the set of tracked computations.
When the reactive data source is modified, it is calling Dependency.changed()
which is going to invalidate every registered computations in the set.
Source : The Meteor Tracker manual.
In the Meteor framework, you usually only deal with several higher level objects implementing the concepts of reactive programming.
Tracker.autorun
, by default template helpers are always run inside a reactive computation.Tracker.Dependency
to invalidate computations, they include MiniMongo cursors, Session
variables, Meteor.user()
, etc...Use Tracker.autorun
when you need to reactively rerun arbitrary code outside of template helpers, for example inside a template onRendered
lifecycle event, use the shortcut this.autorun
(spawning a reactive computation that is automatically stopped when the template is destroyed) to react to any reactive data sources modifications.
Here is a small example of a template that counts how many times you clicked a button and reset the counter to 0 when clicked 10 times.
HTML
<template name="counter"> <div class="counter> <button type="button">Click me !</button> <p>You clicked the button {{count}} times.</p> </div> </template>
JS
Template.counter.onCreated(function(){ this.count = new ReactiveVar(0); }); Template.counter.onRendered(function(){ this.autorun(function(){ var count = this.count.get(); if(count == 10){ this.count.set(0); } }.bind(this)); }); Template.counter.helpers({ count: function(){ return Template.instance().count.get(); } }); Template.counter.events({ "click button": function(event, template){ var count = template.count.get(); template.count.set(count + 1); } });
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With