• Meteor
  • Tutorial

Using wait, waitOn and ready in Routes

In this video, we're going to look at how to use the waitOn option and Iron Router for our routes. And we'll look at how to wait on subscriptions and other custom functions that we might want to wait on and how to use the reactive ready method.

I have a simple route here that I've called Item. And it's at the root path, so we can play with it. And it has an action function, where right now, I'm just rendering out the template called Item, and that template is over here.

And what I would like to be able to do is to subscribe to these two publish functions inside of this route and wait until we get the ready message for each of them before rendering out the Item template. And while we're waiting, I'd like to be able to render this Loading template instead.

I've opened up the app in the browser on the right. And notice that we're rendering out this Item template. And it's also getting a data context, which has a title of One. And that's coming from our data option here.

And so you might be wondering what the difference is between using a data function and a waitOn function. And so I wanted to put this data option here, so that you can see that whatever gets returned is just the global data context for our page. And that's why it's printing One here to the page.

So the next thing we want to do is actually subscribe to these publish functions and to wait on their results. So to do that, I'm going to go into my action function, and I can call a function of the route controller called wait.

And which takes either a function or the result of calling subscribe on a particular Meteor subscription. And so let's go ahead and subscribe to the Item publication. And then we also want to wait on subscribing to comments.

Now what this will do is add both of these subscription handles to a wait list. And if you'd like to know more about how the WaitList Data Structure works, you should check out the WaitList Data Structure video in the feed.

But what this is going to allow us to do is to say, let us know when all of these subscriptions are ready-- in other words, we've gotten the ready messages for each one. To check that, I can just put an if statement and if this.ready. And this will return true if every item in this list is ready and false otherwise.

So if we're ready, I'll go ahead and render out the Item template. And if we're not ready, I'll render out the Loading template instead. When I refresh the page, you'll notice the Loading template gets rendered first.

And then a couple of seconds later, when both of our subscriptions are ready, we render out the Item template. Now let's go back to the action function and take a look at what's happening here.

The reason that this works is that this entire function is run inside of a computation. And so when we call this ready function here, the first time that we call it, the list will not be ready, because we don't have the ready messages for each of these subscriptions.

And so this.ready will be false. And we render out the Loading template because of that. But then what happens is the state of the list changes to true, once all the items in it have been changed to ready, so we have the ready messages for each of these subscriptions.

And what will happen in this case is this entire function will just rerun because it's reactive. And so what will happen then is the whole function will rerun. And this.ready will get called again. And this time, it will be true. And so we'll render out this Item template here instead.

So I found that this is a bit of a tricky concept to get used to. And that is, that this whole function will just rerun every time the state changes. And the state, in this case, is when the value of calling this.ready changes from true to false or false to true.

Now, we can also add custom functions to the wait list. And so far, we've just added two subscription handles. But I can add a function that returns a true or false value reactively.

For example, I might just return a value that I get from Session. So in this example, this item will be ready when Session.get is ready is true.

OK, so we'll wait for hot code push to work. And when the browser reloads, we should stay on this Loading page now until we change the Session value is ready to true.

Now at this point, we've already received the two ready messages for our subscriptions. But we're still showing the Loading template on the page. And that's because we have this last thing that we're waiting on here, which we're going to control manually using Session.

So if I come down into the console and set this Session value from undefined to true, that will rerun our action function. And now we render out the Item template again to the page.

Now, to just make sure how many times this action function is rerunning, let's put a console log here. And I'll actually print out the results of calling this.ready. And I'll save that and refresh the browser.

And then we'll go into the console and say Session.set is ready to true. Notice that the function only reruns once. It runs the first time, and they ready state is false, because we're still waiting on that session variable to be true.

And then once the overall state of the list changes to ready, it reruns the action function again. So far, we've been calling the wait function in order to add things to the wait list.

We added an extra kind of helper feature to subscription, so that you can actually call this.subscribe and call the wait function on the resulting handle. And that will do the same thing as what this is doing here.

So this is more of just kind of a convenience. But I wanted to show you that it's the same thing. These two statements here are equivalent.

The other thing is that so far we've been calling this.wait inside of our action function. But you've probably heard a lot about this method or option called waitOn. And so next, I'd like to talk about why you can use that and what it's for.

So when we call this.wait, what we're doing is we're populating this wait list, like we've talked about. And we're calling the ready method to see whether every item in the list is ready.

What you can use waitOn for is to populate that wait list as well. But with waitOn, we use the return value to decide what goes into the list.

So for example, if I wanted to wait on these three items that I've waited on down here, I'd return an array. And inside of that array, I would subscribe to Item and to Comments and then even to my custom function, where I return this is ready session variable.

And since we have our return value here, I can get rid of these three calls to the wait function. Over in the browser, we're back on the Loading page now. And you can see the action console log has printed once that we're not ready yet.

And just to make sure that it's clear what's happening, I'm going to set the Session variable now to true. And our action function should rerun, and we print out the template again.

So you might be wondering, well, why do we use this waitOn option at all? Why not just call the wait function inside of our action? And the reason is that this waitOn function will execute before anything else in our route, including hooks.

And so what this allows us to do is to populate the wait list up front, before anything else runs. Let me show you an example of a hook that might use the ready state of the route.

I've created this hook up here. And I've added it using the on before action. And so I want this function to run before our action function down here. And the reason we might create it as a hook is if this functionality applies to multiple routes in our application or if a package author created it themselves.

Inside of this function, I basically want to copy and paste all of this. And this time, we're just going to say, if we're not ready, then render the Loading template. And then we'll pause, so that the downstream functions don't run.

And then we can come in here and get rid of this all together. And what's happening here is that in our hook, in order to know whether we're ready or not, we need that wait list to be populated. And it's already populated at this point, because we put all of our wait stuff inside of this waitOn option here.

So if we didn't have any hooks, we could just simply call wait inside of our action function. And that would do the same thing as returning them all in an array in this waitOn option.

In this video, we covered what it means to you wait on subscriptions inside of Iron Router. And we also looked at how to use the wait method and to use the waitOn option.

If you'd like to know more about how the wait list is implemented, you should go check out the WaitList Data Structure feed video.

And if you'd like to see more about what it actually means to wait on a subscription and what the ready message means, you should go check out the "Waiting on Subscriptions" video. I hope this made the waitOn option a little bit more clear for you.