我认为我的Meteor客户端启动代码遇到了竞争状态。
简要背景
我正在使用Meteor进行HTML5游戏大厅界面。当用户通过刷新页面或稍后返回返回菜单时,我希望客户端找到该用户正在进行的任何游戏。但是,我无法在启动期间访问任何集合。
我的client.js
文件顶部的摘录如下所示。
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? ***********
}
});
}
但是,从javascript控制台我可以运行Players.findOne({"user_id":Meteor.userId());
,它可以返回一个有效的播放器就好了。 我的收藏品与这种竞争条件有什么关系?
编辑1:
深入了解库我发现我错误地认为来自服务器的数据会立即可用。订阅实际上需要一段时间来处理,这就是为什么它们在客户端启动时不可用。我正在更新我的问题以表达这些新信息。
更新问题
由于我依靠多个订阅为用户(玩家和游戏)找到游戏,有没有Meteor方式等待两者?为获得正在进行的游戏而单独订阅似乎是错误的。所以需要任何服务器调用。
我觉得一旦他们进来就能从找到的玩家和游戏中找到我需要的游戏而不再打扰服务器。
一旦找到自己的解决方案,我会在这里发布。
答案 0 :(得分:2)
好的,这就是我的工作:
基本上我在会话中添加了两个订阅的就绪回调设置的标志。然后Deps.autorun
函数侦听要设置的Session值,并完成剩下的工作。
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");
});
}
希望我能帮助某人。