Skip to content
This repository has been archived by the owner on Oct 24, 2021. It is now read-only.

Commit

Permalink
Make Meteor.autosubscribe a deprecated alias for Meteor.autorun.
Browse files Browse the repository at this point in the history
Instead of a general client-side sub de-duping mechanism (which mostly existed
for the sake of autosubscribe, and causes issues with server-driven
unsubscribes), make Meteor.subscribe explicitly aware of reactivity.

Expose an "invalidated" flag on Meteor.deps.Context.

Guarantee that invalidation callbacks from different contexts will not be
interleaved at flush time. This has the implication that if you do

   context1.onInvalidate(function () {
     context2.invalidate();
   });

and this is the only way to invalidate context2, then context2's invalidation
callbacks will not be called until after *ALL* of context1's callbacks are
called. This allows us to be sure that the "unsubscribe, unless autorun tried to
re-create an identical sub" logic runs after the autorun function is rerun.
  • Loading branch information
glasser committed Jan 15, 2013
1 parent 69e1c81 commit 65537e1
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 55 deletions.
72 changes: 36 additions & 36 deletions client/api.html
Expand Up @@ -106,8 +106,8 @@ <h2 id="publishandsubscribe"><span>Publish and subscribe</span></h2>
// client: declare collection to hold count object
Counts = new Meteor.Collection("counts");

// client: autosubscribe to the count for the current room
Meteor.autosubscribe(function () {
// client: subscribe to the count for the current room
Meteor.autorun(function () {
Meteor.subscribe("counts-by-room", Session.get("roomId"));
});

Expand Down Expand Up @@ -161,34 +161,31 @@ <h2 id="publishandsubscribe"><span>Publish and subscribe</span></h2>
activated. (Even if it is not the first to send the duplicated
attribute.)

If you call [`Meteor.subscribe`](#meteor_subscribe) within a [reactive
context](#reactivity) such as [`Meteor.autorun`](#meteor_autorun), the
subscription will automatically be cancelled when the context is invalidated;
it's not necessary to call `stop` on subscriptions made from inside
`Meteor.autorun`. However, if the next iteration of your autorun function
subscribes to the same record set (same name and parameters), Meteor is smart
enough to skip a wasteful unsubscribe/resubscribe. For example:

Meteor.autorun(function () {
Meteor.subscribe("chat", {room: Session.get("current-room")});
Meteor.subscribe("privateMessages");
});

This subscribes you to the chat messages in the current room and to your private
messages. When you change rooms by calling `Session.set("current-room",
"new-room")`, Meteor will subscribe to the new room's chat messages,
unsubscribe from the original room's chat messages, and continue to
stay subscribed to your private messages.

If all of the attributes in a document are removed, Meteor
will remove the (now empty) document. If you want to publish empty
documents, just use a placeholder attribute:

Clicks.insert({exists: true});

{{> api_box autosubscribe}}

`func` will be run immediately, and while it runs,
records will be kept of the subscriptions it makes
(via [`Meteor.subscribe`](#meteor_subscribe)) and the data it uses
(including calls to [`Session.get`](#session_get)
and [`collection.find`](#find)).

Whenever the used data changes, the subscriptions will be cancelled and
`func` will be re-run to make replacement subscriptions.
`Meteor.autosubscribe` will automatically stop the old subscription.
It's not necessary to call `stop` on subscriptions made from inside
`Meteor.autosubscribe`.

Example:

// Subscribe to the chat messages in the current room. Automatically
// update the subscription whenever the current room changes.
Meteor.autosubscribe(function () {
Meteor.subscribe("chat", {room: Session.get("current-room")});
});

<h2 id="methods_header"><span>Methods</span></h2>

Methods are remote functions that Meteor clients can invoke.
Expand Down Expand Up @@ -566,7 +563,7 @@ <h2 id="collections"><span>Collections</span></h2>
Cursors are a reactive data source. The first time you retrieve a
cursor's documents with `fetch`, `map`, or `forEach` inside a
reactive context (eg, [`Meteor.render`](#meteor_render) or
[`Meteor.autosubscribe`](#meteor_autosubscribe)), Meteor will register a
[`Meteor.autorun`](#meteor_autorun)), Meteor will register a
dependency on the underlying data. Any change to the collection that
changes the documents in a cursor will trigger a recomputation. To
disable this behavior, pass `{reactive: false}` as an option to
Expand Down Expand Up @@ -1063,11 +1060,11 @@ <h2 id="session"><span>Session</span></h2>

Example:

Meteor.autosubcribe(function () {
Meteor.autorun(function () {
Meteor.subscribe("chat-history", {room: Session.get("currentRoomId")});
});

// Causes the function passed to Meteor.autosubscribe to be re-run, so
// Causes the function passed to Meteor.autorun to be re-run, so
// that the chat-history subscription is moved to the room "home".
Session.set("currentRoomId", "home");

Expand Down Expand Up @@ -2136,9 +2133,11 @@ <h2 id="meteor_deps"><span>Meteor.deps</span></h2>
it can know when to stop listening for changes.

Invalidation contexts have an `id` attribute, which is a unique positive
integer. You're free to add any other attributes you like to the
invalidation context for your own convenience, as long as they don't
start with an underscore.
integer, and a boolean attribute `invalidated`. `invalidated` starts out false,
and is set to true when `invalidate` is called, before calling any of the
invalidation callbacks. You're free to add any other attributes you like to the
invalidation context for your own convenience, as long as they don't start with
an underscore.

{{> api_box run }}

Expand Down Expand Up @@ -2321,12 +2320,13 @@ <h2 id="meteor_deps"><span>Meteor.deps</span></h2>
[`Meteor.render`](#meteor_render) have already been inserted in the main
DOM tree.

Technically speaking, `flush` calls the [invalidation
callbacks](#oninvalidate) on every [reactive context](#context) that
has been [invalidated](#invalidate), but hasn't yet had its callbacks
called. If the invalidation callbacks invalidate still more contexts,
flush keeps flushing until everything is totally settled. The DOM
elements are cleaned up by logic that is triggered by context invalidations.
Technically speaking, `flush` calls the [invalidation callbacks](#oninvalidate)
on every [reactive context](#context) that has been [invalidated](#invalidate),
but hasn't yet had its callbacks called. If the invalidation callbacks
invalidate still more contexts, flush keeps flushing until everything is totally
settled. In this case, the callbacks on the newly-invalidated context won't be
called until after the currently-flushing context's callbacks have all been
run.



Expand Down
14 changes: 1 addition & 13 deletions client/api.js
Expand Up @@ -182,18 +182,6 @@ Template.api.subscribe = {
]
};

Template.api.autosubscribe = {
id: "meteor_autosubscribe",
name: "Meteor.autosubscribe(func)",
locus: "Client",
descr: ["Automatically set up and tear down subscriptions."],
args: [
{name: "func",
type: "Function",
descr: "A [`reactive`](#reactivity) function that sets up some subscriptions by calling [`Meteor.subscribe`](#meteor_subscribe). It will automatically be re-run when its dependencies change."}
]
};

Template.api.methods = {
id: "meteor_methods",
name: "Meteor.methods(methods)",
Expand Down Expand Up @@ -1215,7 +1203,7 @@ Template.api.set = {
id: "session_set",
name: "Session.set(key, value)",
locus: "Client",
descr: ["Set a variable in the session. Notify any listeners that the value has changed (eg: redraw templates, and rerun any [`Meteor.autosubscribe`](#meteor_autosubscribe) blocks, that called [`Session.get`](#session_get) on this `key`.)"],
descr: ["Set a variable in the session. Notify any listeners that the value has changed (eg: redraw templates, and rerun any [`Meteor.autorun`](#meteor_autorun) blocks, that called [`Session.get`](#session_get) on this `key`.)"],
args: [
{name: "key",
type: "String",
Expand Down
11 changes: 7 additions & 4 deletions client/concepts.html
Expand Up @@ -251,7 +251,7 @@ <h2 id="reactivity">Reactivity</h2>
you can write your code in a simple imperative style, and the result will be
automatically recalculated whenever data changes that your code depends on.

Meteor.autosubscribe(function () {
Meteor.autorun(function () {
Meteor.subscribe("messages", Session.get("currentRoomId"));
});

Expand All @@ -262,8 +262,8 @@ <h2 id="reactivity">Reactivity</h2>
replaces the old one.

This automatic recomputation is achieved by a cooperation
between `Session` and `Meteor.autosubscribe`.
Methods like `Meteor.autosubscribe` establish a "reactive
between `Session` and `Meteor.autorun`.
Methods like `Meteor.autorun` establish a "reactive
context" inside of which data dependencies are tracked, and they are
prepared to re-run their function argument as necessary. Data
providers like `Session`, on the other hand, make note of
Expand All @@ -281,7 +281,6 @@ <h2 id="reactivity">Reactivity</h2>

* [Templates](#templates)
* [`Meteor.render`](#meteor_render) and [`Meteor.renderList`](#meteor_renderlist)
* [`Meteor.autosubscribe`](#meteor_autosubscribe)
* [`Meteor.autorun`](#meteor_autorun)

And the reactive data sources that can trigger changes are:
Expand All @@ -293,6 +292,10 @@ <h2 id="reactivity">Reactivity</h2>
* [`Meteor.userId`](#meteor_userid)
* [`Meteor.loggingIn`](#meteor_loggingin)

In addition, calling [`Meteor.subscribe`](#meteor_subscribe) in a reactive
context sets up a subscription which is automatically stopped when the context
is invalidated, as shown above.

Meteor's
[implementation](https://github.com/meteor/meteor/blob/master/packages/deps/deps.js)
of reactivity is short and sweet, about 50 lines of code. You can hook into it
Expand Down
3 changes: 1 addition & 2 deletions client/docs.js
Expand Up @@ -108,8 +108,7 @@ var toc = [
{instance: "this", name: "onStop", id: "publish_onstop"},
{instance: "this", name: "stop", id: "publish_stop"}
],
"Meteor.subscribe",
"Meteor.autosubscribe"
"Meteor.subscribe"
],

{name: "Methods", id: "methods_header"}, [
Expand Down

0 comments on commit 65537e1

Please sign in to comment.