14

I want to perform a Meteor collection query as soon as possible after page-load. The first thing I tried was something like this:

Games = new Meteor.Collection("games");
if (Meteor.isClient) {
  Meteor.startup(function() {
    console.log(Games.findOne({}));
  }); 
}

This doesn't work, though (it prints "undefined"). The same query works a few seconds later when invoked from the JavaScript console. I assume there's some kind of lag before the database is ready. So how can I tell when this query will succeed?

Meteor version 0.5.7 (7b1bf062b9) under OSX 10.8 and Chrome 25.

Derek Thurn
  • 14,953
  • 9
  • 42
  • 64
  • Where do you actually need to use this? Would it be possible to put the call in a `Template`? – Swadq Feb 28 '13 at 08:06
  • No, I want to read a URL parameter and possibly redirect the browser if it's not found in the database. – Derek Thurn Mar 01 '13 at 05:39
  • Pretty much a duplicate of [Displaying loader while meteor collection loads](http://stackoverflow.com/questions/12879762/displaying-loader-while-meteor-collection-loads) – Dan Dascalescu May 19 '14 at 15:42

6 Answers6

17

You should first publish the data from the server.

if(Meteor.isServer) {
    Meteor.publish('default_db_data', function(){
        return Games.find({});
    });
}

On the client, perform the collection queries only after the data have been loaded from the server. This can be done by using a reactive session inside the subscribe calls.

if (Meteor.isClient) {
  Meteor.startup(function() {
     Session.set('data_loaded', false); 
  }); 

  Meteor.subscribe('default_db_data', function(){
     //Set the reactive session as true to indicate that the data have been loaded
     Session.set('data_loaded', true); 
  });
}

Now when you perform collection queries, you can check if the data is loaded or not as:

if(Session.get('data_loaded')){
     Games.find({});
}

Note: Remove autopublish package, it publishes all your data by default to the client and is poor practice.

To remove it, execute $ meteor remove autopublish on every project from the root project directory.

EpokK
  • 38,062
  • 9
  • 61
  • 69
sohel khalifa
  • 5,602
  • 3
  • 34
  • 46
  • I went with this approach and things worked out. The callback to Meteor.subscribe is invoked when the database is ready. – Derek Thurn Mar 03 '13 at 02:09
  • 3
    Is there a reason you're not using a subscription handle and the `ready()` method here? – Jonatan Littke Aug 27 '13 at 14:11
  • 1
    Very strange solution! On my actual meteor (0.6.6.2) this line "this.ready()" do completely opposite thing - fires ready event on my client before real data ready. If you coment it you can use callback as @Jonatan says. – peko Oct 28 '13 at 21:31
  • Should we use 'default_db_data'? Is that a built in collection we can use to check if the database is ready? – malhal Aug 30 '14 at 12:53
  • 3
    2015 update: now we have [Template.instance().subscriptionsReady()](http://stackoverflow.com/questions/12879762/displaying-loader-while-meteor-collection-loads/12880255#12880255). – Dan Dascalescu Apr 05 '15 at 19:52
8

Use DDP._allSubscriptionsReady() (Meteor 0.7)

Denis Gorbachev
  • 507
  • 4
  • 12
  • 4
    2015 update: now we have the official [Template.instance().subscriptionsReady()](http://stackoverflow.com/questions/12879762/displaying-loader-while-meteor-collection-loads/12880255#12880255). – Dan Dascalescu Apr 05 '15 at 19:52
6

As of Meteor 1.0.4, there is a helper that tells you exactly when a particular subscription is ready: Template.instance().subscriptionsReady().

Since this question is a duplicate, please check my answer in the original question, Displaying loader while meteor collection loads.

Community
  • 1
  • 1
Dan Dascalescu
  • 143,271
  • 52
  • 317
  • 404
  • @malhal it is referring to the template. From the [docs](http://docs.meteor.com/api/templates.html#Template-instance): The template instance corresponding to the current template helper, event handler, callback, or autorun. If there isn't one, null. – Anima-t3d Jun 24 '16 at 06:10
1

You can also do template level subscriptions:

Template.name.onCreated(function(){
var self = this;

this.autorun(function(){

const db = this.subscribe('publicationname', [,args]);

if(db.isReady()){
 "You'll know it's ready here" .. do what you need.
 }
 });
})

This makes it easier to know inside the template too. you can just call {{#if Template.subscriptionsReady}} {{else}} Loading Screen may be
{{/if}}

0

You could check when a result is finally returned if you know that your Games collection is never empty:

Meteor.autorun(function() {
    if(Games.findOne() && !Session.get("loaded")) {
        Session.set("loaded",true);

        //Its ready..
        console.log(Games.findOne({}));
    }
});

You can also use this in your templates:

Client js:

Template.home.isReady = function() { return Session.get("loaded") };

Html

<template name="home">
    {{#if isReady}}
        Yay! We're loaded!!
    {{else}}
        Hold an a second
    {{/if}}
</template>
Tarang
  • 75,157
  • 39
  • 215
  • 276
  • 2015 update: now we have [Template.instance().subscriptionsReady()](http://stackoverflow.com/questions/12879762/displaying-loader-while-meteor-collection-loads/12880255#12880255). – Dan Dascalescu Apr 05 '15 at 19:51
0

Here is another tidbit of information for those who may be using userid or some part of user info stored in Meteor.users database. When the page first loads the Meteor subscribe, going on in the background, may not be complete itself. Therefor when you try to connect to another database to query for that, it will not pull the information. This is because the Meteor.user() is still null itself;

The reason, like said above, is because the actual Meteor users collection has not gotten through pulling the data.

Simple way to deal with this.

Meteor.status().connected

This will return true or false, to let you know when the Meteor.user collection is ready. Then you can go on about your business.

I hope this helps someone, I was about to pull my hair out trying to figure out how to check the status. That was after figuring out the Meteor user collection itself was not loaded yet.

  • Maybe I'm misunderstanding what `Meteor.status().connected` represents, but there is a flash when `connected` is true but `Meteor.user()` is null. – Smokin Joe Sep 14 '17 at 00:01