1

My meteor directory is consists of 2 files:

social.js:

Messages = new Meteor.Collection("messages");

if (Meteor.isServer) {
}

if (Meteor.isClient) {
    Template.temple.messages = function() {
        return Messages.find();  
    };

    Meteor.startup(function () {
            console.log('console startup: ' + Messages.find().count());
    });

    console.log('console normal: ' + Messages.find().count());

    var ali = function() {
        console.log('console normal: ' + Messages.find().count());
    };

    setTimeout(function() {
        console.log('console normal: ' + Messages.find().count());
    }, 2000);
    // The callback function is not called on the following line:
    Meteor.subscribe('messages',function(){alert('ALERT!');});
}

social.html:

<head>
<title>naber</title>
</head>

<body>
{{> temple}}
</body>

<template name = "temple">
{{#each messages}}
{{message}} <br />
{{/each}}
</template>

The collection is fully loaded only after some time has passed. I can only see the true count of documents if I wrap around a setTimeout. What can I do to ensure that my functions are executed after the database is truly and fully available?

osolmaz
  • 1,873
  • 2
  • 24
  • 41

3 Answers3

2

Meteor.subscribe(NAME) pairs with Meteor.publish(NAME). Your code tries to subscribe to something called "messages" but you're not publishing something with that name.

The fact that you're getting data at all suggests that you are using the default autopublish package (see .meteor/packages to check), which means that you neither have to explicitly publish or subscribe to data. Unfortunately, there's no way to get a callback when autopublished data is ready (which should probably be fixed). So if you want to do this, you'll want to meteor remove autopublish and use Meteor.publish to publish the data you want published; then, you actually can use the Meteor.subscribe callback.

David Glasser
  • 1,438
  • 13
  • 21
1

I usually show a loading indicator till the subscription is loaded. See this for an example: Meteorjs loading message

To publish the collection from the server-side:

if (Meteor.isServer) {
  Meteor.publish("messages", function () {
    return Messages.find(); // everything
  );
}
Community
  • 1
  • 1
Mandar Limaye
  • 1,900
  • 16
  • 24
  • For some reason, the ``onComplete`` function is not called. I edited the example, and it still doesn't work. You can add documents to the database by ``Messages.insert({message:'lolmessage'})`` from the console. – osolmaz Jan 26 '13 at 11:43
  • It worked ^^. But I suppose ``Meteor.autorun`` is better for such tasks. – osolmaz Jan 27 '13 at 14:48
1

Because of how reactivity in Meteor works, there is always an application state you need to design for where the server has not yet sent the data to the client yet. You can call this the "loading" state.

Within Template declarations, you must always check whether data you depend on is available. If the template does depend on data, expect it first to render empty and then to update when data arrives, since the data is a reactive data source.

With your own functions, it's best to write them in such a way that they also depend on a reactive data source and use something like Meteor.autorun to make sure they're re-executed when such data sources change.

Always put code that you want to run after the page loads inside Meteor.startup, or you risk not even having Meteor available when your code executes.

Here's how I would rewrite your code:

Messages = new Meteor.Collection("messages");
if (Meteor.isClient){
  Meteor.startup(function() {
    // anything you need to do, like subscriptions 
  });
  Template.temple.loading = function() {
    return Messages.find().count === 0 ? "Loading..." : "";
  }
  Template.temple.messages = function() {
    var messages = Messages.find();
    if (messages.count() > 0) return messages;
  }
}

<template name="messages">
  {{loading}}
  {{#each messages}}
    {{message}}<br>
  {{/messages}}
</template>

You don't actually need a Meteor.subscribe call to messages if you're just using Messages.find() on the client.

Rahul
  • 12,181
  • 5
  • 43
  • 64