Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Subscribing to a reactive data source using autorun

Tags:

meteor

I'm trying to write a webapp using Meteor and I'm definitely failing to grok something about subscribing to published datasets. The entire app is up on github (linked to the latest commit for posterity), but I'll try to summarize below.

I have a collection called teams which is available to both client and server:

Teams = new Meteor.Collection( "teams" );

On the server, I want to publish a list of all of the teams:

Meteor.publish( "allteams", function() { ...

There's a very simple cursor which makes up this published list:

var handle = Teams.find( {} ).observeChanges({
    added: function( id ) {
        console.log( "New team added" );
        if ( !initializing ) {
            console.log( "Telling subscribers it's all change" );
            self.added( "teams", id, {} );
            self.ready();
        }
    }
});

The client subscribes to that source, and when elements are added the client will add pins to a map:

Meteor.autorun( function() {
    Meteor.subscribe( "allteams", function() {
        console.log( "All teams has been updated" );
        // Do more stuff
    }
};

When the list is initially populated the autorun runs fine, but if I add another element to the collection then the publisher method logs to say "I noticed this" but nothing happens in the subscriber.

The aim of the above is as follows:

  • There is a list of teams on the server which consists of a name and long/lat details
  • When a client connects, they receive that list of teams and they're plotted on a map
  • If a team is added to the list on the server side, each client is notified and a new pin appears on the map.

In terms of the app, I probably don't need pins to magically appear, but it's a useful way of learning publish and subscribe, especially when I don't get it right! Eventually, "allteams" will probably be a bit more fine-grained than just the entire list of teams, so I guess it's akin to making a view on the data.

Am I missing something completely obvious?

Edit: I worked it out and put the answer below. tl;dr I wasn't subscribing to a reactive data source at all.

like image 404
chooban Avatar asked Dec 11 '22 16:12

chooban


1 Answers

It's probably not polite to answer my own question, but I worked out what I was doing wrong and I figured that other people might come across the same thing.

Simple answer is that I wasn't doing what I claimed to be doing in the title of the queston, specifically, not subscribing to a reactive data source.

Meteor.autorun( function() {
    Meteor.subscribe( "allteams", function() {
        console.log( "All teams has been updated" );
        // Do more stuff
    }
};

Here I've passed the subscribe method to autorun, but that method itself isn't a reactive data source. However, it returns something which is!

// Define a subscription
var handle = Meteor.subscribe( "foo", { onReady: function() { ... } } );

Meteor.autorun( function() {
    if ( handle.ready() ) {
        // Now do something every time the subscription is marked as ready
    }
};

The ready method of a subscription handle is reactive, so the autorun now executes every time the published document set is updated. That leads me to further questions about the efficiency of multiple clients subscribing to a database cursor and watching for changes, but I'll come to that in another question.

like image 147
chooban Avatar answered Jan 16 '23 10:01

chooban