Waiting for meteor collection to finish before next step

javascript, meteor

Solution

You are right, you should ensure that code depending on fetching the content of a client-side subscribed collection is executed AFTER the data is properly loaded.

You can achieve this using a new pattern introduced in Meteor 1.0.4 : https://docs.meteor.com/#/full/Blaze-TemplateInstance-subscribe

`client/views/svg/svg.js`

Template.outer.onCreated(function(){
  // subscribe to the publication responsible for sending the Pushups
  // documents down to the client
  this.subscribe("pushupsPub");
});

`client/views/svg/svg.html`

<template name="outer">
  {{#if Template.subscriptionsReady}}
    {{> svgTemplate}}
  {{else}}
    Loading...
  {{/if}}
</template>

In the Spacebars template declaration, we use an encapsulating `outer` template to handle the template level subscription pattern. We subscribe to the publication in the `onCreated` lifecycle event, and we use the special reactive helper `Template.subscriptionsReady` to only render the `svgTemplate` once the subscription is ready (data is available in the browser). At this point, we can safely query the `Pushups` collection in the `svgTemplate` `onRendered` lifecycle event because we made sure data made its way to the client :

Template.svgTemplate.onRendered(function(){
  console.log(Pushups.find().fetch());
});

Alternatively, you could use the `iron:router` (https://github.com/iron-meteor/iron-router), which provides another design pattern to achieve this common Meteor related issue, moving subscription handling at the route level instead of template level.

Add the package to your project :

meteor add iron:router

`lib/router.js`

Router.route("/svg", {
  name: "svg",
  template: "svgTemplate",
  waitOn: function(){
    // waitOn makes sure that this publication is ready before rendering your template
    return Meteor.subscribe("publication");
  },
  data: function(){
    // this will be used as the current data context in your template
    return Pushups.find(/*...*/);
  }
});

Using this simple piece of code you'll get what you want plus a lot of added functionalities. You can have a look at the Iron Router guide which explains in great details these features.

https://github.com/iron-meteor/iron-router/blob/devel/Guide.md

EDIT 18/3/2015 : reworked the answer because it contained outdated material and still received upvotes nonetheless.

Problem

I have a Meteor template that should be displaying some data. ``` Template.svg_template.rendered = function () { dataset_collection = Pushups.find({},{fields: { date:1, data:1 }}, {sort: {date: -1}}).fetch(); a = moment(dataset_collection[0].date, "YYYY/M/D"); //more code follows that is also dependent on the collection being completely loaded }; ``` Sometimes it works, sometimes I get this error: Exception from Deps afterFlush function: TypeError: Cannot read property 'date' of undefined I'm not using Deps in any context. As I understand it, the collection is being referenced before it is completely finished loading. I therefore would like to figure out how to simply say "wait until the collection is found before moving on." Should be straightforward, but can't find an updated solution.

Original source