22

Why this code shows "0"? Shouldn't it return "1"?

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

if (Meteor.is_client) {
    Meteor.startup(function () {    
        alert(Messages.find().count());
    });
}

if (Meteor.is_server) {
    Meteor.startup(function () {
        Messages.insert({text: "server says hello"});
    });
}

If I do the "Messages.find().count()" later, it returns 1.

pomber
  • 23,132
  • 10
  • 81
  • 94
  • 1
    @Raynos It doesn't look like a concurrency problem. It happens every time the client startup handler is executed. – pomber Apr 11 '12 at 05:38
  • It is a concurrency issue, the issue is that your running two things concurrently one on the server and one on the client. and your expecting the server one to magically finish first – Raynos Apr 11 '12 at 05:47
  • 5
    @Raynos The insert in the server runs only once, when the server is started. The find in the client runs multiple times any time later. – pomber Apr 11 '12 at 23:01

2 Answers2

37

By default, when a Meteor client starts up, it connects to the server and subscribes to documents in any Meteor.Collection you defined. That takes some time to complete, since there's always some amount of delay in establishing the server connection and receiving documents.

Meteor.startup() on the client is a lot like $() in jQuery -- it runs its argument once the client DOM is ready. It does not wait for your client's collections to receive all their documents from the server. So the way you wrote the code, the call to find() will always run too early and return 0.

If you want to wait to run code until after a collection is first downloaded from the server, you need to use Meteor.subscribe() to explicitly subscribe to a collection. subscribe() takes a callback that will run when the initial set of documents are on the client.

See:

meteor-publish and meteor-subscribe

debergalis
  • 11,870
  • 2
  • 49
  • 43
  • When using `Meteor.subscribe()` do i have to somehow turn off the default "subscribe to all documents of a collection" behaviour? – bijan Jun 20 '12 at 16:57
  • 3
    @bijan (or for others who'd have the same question), yes you need to remove the autopublish package: $ meteor remove autopublish. – WispyCloud Sep 02 '12 at 07:10
0

Just to follow up with a code example of how to know when a collection is ready to use on the client.

As @debergalis described, you should use the Meteor.subscribe approach - it accepts a couple of callbacks, notably onReady

For example:

if(Meteor.isClient){

    Meteor.subscribe("myCollection", {

        onReady: function(){

            // do stuff with my collection

        }

    });

}
Community
  • 1
  • 1
danwild
  • 1,886
  • 1
  • 26
  • 31