How does Meteor's reactivity work behind the scenes?

Meteor

Meteor Problem Overview


I have read the http://docs.meteor.com/">docs</a> and looked at the https://github.com/meteor/meteor/blob/master/packages/tracker/tracker.js">source behind reactivity, but I don't understand it.

Can someone explain how this works behind the scenes, as it looks like magic to me :).

Meteor Solutions


Solution 1 - Meteor

So it's actually rather straight forward, at a basic level there are 2 types of functions involved:

  1. Functions that create a reactive context (reactive function)

  2. Functions that invalidate a reactive context (invalidating function)

  3. Functions that can do both. (I lied there are 3)

When you call a reactive function it creates a context that meteor stores globally and to which the reactive function subscribes an invalidation callback. The function that you pass to a reactive function, or any functions that run from within it, can be an invalidating function and can grab the current context and store it locally. These functions can then at any time, like on a db update or simply a timer call, invalidate that context. The original reactive function would then receive that event and re-evaluate itself.

Here's a step by step using meteor functions (note that Tracker.autorun used to be called Deps.autorun):

Tracker.autorun(function(){ 
  alert("Hello " + Session.get("name"));
});

Session.set("name", "Greg");
  1. autorun takes a function as its parameter

  2. before autorun runs this function, it creates a context

  3. autorun attaches a callback to the context's invalidation event

  4. This callback will re-run the function passed to autorun

  5. The function is then run in the context for the first time.

  6. Meteor stores this context globally as the currently active context

  7. Inside the function is another function: Session.get()

  8. Session.get() is both a reactive function and an invalidating function

  9. Session.get sets up it's own context and associates it internally with the key "name"

  10. Session.get retrieves the current context (autorun's context) globally from meteor

  11. The invalidation callback that Session.get registers to it's own context, will simply invalidate it's enclosing context (in this case, autorun's context)

  12. So now we have 2 contexts, autorun's and session.get's

  13. when these functions return, meteor cleans up the active context global variable

  14. Session.set is another function capable of invalidating a context.

  15. in this case we're invalidating all contexts created by Session associated with the key "name"

  16. All of those contexts, when invalidated, run their invalidation callbacks.

  17. Those callbacks just invalidate their enclosing contexts (That's the design of Session.get and not what a invalidation callback must do)

  18. Those enclosing contexts now run their invalidation callbacks.

  19. In the autorun case, that callback runs the function we originally passed to autorun and then sets up the context again.

The whole implementation is actually rather straight forward as well, you can see it here:
https://github.com/meteor/meteor/blob/master/packages/tracker/tracker.js

And a good example of how it works can be found here:
https://github.com/meteor/meteor/blob/master/packages/reactive-dict/reactive-dict.js

Reactive programming is not actually meteor or JS specific
you can read about it here: http://en.wikipedia.org/wiki/Reactive_programming

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionduality_View Question on Stackoverflow
Solution 1 - MeteorgreggregView Answer on Stackoverflow