简体   繁体   中英

Waiting for multiple subscriptions on client-side cases of Meteor.startup

I think I'm hitting a race condition on my Meteor client startup code.

Brief background

I'm using Meteor for a HTML5 game lobby interface. When a user returns to the menu by refreshing the page or returning later, I want the client to find any games in progress for that user. However, I can't access any Collections during startup.

An excerpt from the top of my client.js file is shown below.

Meteor.subscribe("players"); //Meteor.Collection("players" references Meteor.users via user_id
Meteor.subscribe("games");  // each player has a game_id, linked to Meteor.Collection("games"
if (Meteor.isClient) {
  Meteor.startup(function () {
      //find the player from the user_id, find game from player.game_id
      var current_user_id = Meteor.userId();
      var playerFromUser = Players.findOne({"user_id":current_user_id});
      if(typeof playerFromUser !== 'undefined'){
          var getGame = Games.findOne(playerFromUser.game_id);
          if(typeof getGame !== 'undefined'){
              alert('game found!'); //is not reached
          }else{
              alert('game not found'); //is not reached
          }
       }else{
          alert('player not found'); //*********** IS reached. Why? *********** 
       }
  });
}

However, from the javascript console I can run Players.findOne({"user_id":Meteor.userId()); and it can return a valid Player just fine. What's up with this race condition with my collections?

EDIT 1:

Looking deeper into the library I see that I was incorrectly assuming the data from the server would be immediately available. The subscriptions actually take a while to process, which was why they aren't available right when the client starts. I'm updating my question to express this new information.

Updated Question

Since I rely on multiple subscriptions to find a game for a user (both Players and Games), is there a Meteor way to wait for both? Having a separate subscription just for getting a possible game in progress seems wrong. So does requiring any server call at all.

I feel should be able to find the game I need from the retrieved players and games once they come in and not bother the server with any more calls.

I'll post here once I find my own solution.

Alright, here's what I have which seems to work:

Basically I added flags in the session that are set on the ready callbacks of the two subscriptions. Then the Deps.autorun function listens for those Session values to be set and does the rest.

if (Meteor.isClient) {
Meteor.subscribe("players", function(){
    console.log("players_loaded ");
    Session.set('players_loaded', true);
}); //linked to Meteor.users with user_id


Meteor.subscribe("games", function(){
   console.log("games_loaded ");
   Session.set('games_loaded', true); 
});  // each player has a game_id


Deps.autorun(function(){
    var gamesLoaded = Session.get('games_loaded');
    var playersLoaded = Session.get('players_loaded');
    if(gamesLoaded && playersLoaded && 
        (typeof Players !== 'undefined')  && (typeof Games !== 'undefined') ) {
        console.log("both loaded! ");
        //find the player from the user_id, find game from player.game_id
        var playerFromUser = Players.findOne({"user_id":Meteor.userId()});
        if(typeof playerFromUser !== 'undefined'){
          var getGame = Games.findOne(playerFromUser.game_id);
          if(typeof getGame !== 'undefined'){
              console.log("game found : " + getGame);
              //Do stuff with the game now that we have it
          }else{
              console.log("no game :(");
          }
        }else{
            console.log("no player :(");
        }
    }
});

Meteor.startup(function () {
  Session.set("title", "whatever else");
  Session.set("games_loaded", false);
  Session.set("players_loaded", false);
  console.log("DOM loaded");
});

}

Here's hoping I helped somebody.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM