5

我在 Meteor 中构建了一个简单的实时多人数学游戏,您可以在这里试用:http: //mathplay.meteor.com

在本地播放时(使用不同的浏览器),一切正常。但是当我和朋友在网上玩游戏时,客户端经常不同步:一个玩家列出的问题实际上已经被另一个玩家解决了。

我的猜测是,一些应该是仅服务器的代码会在其中一个客户端上执行。有关如何调试此行为的任何建议?

以下是用户提交答案时客户端发生的情况:

Template.number_input.events[okcancel_events('#answertextbox')] = make_okcancel_handler({
    ok: function (text, event) {
        question = Questions.findOne({ order_number: Session.get("current_question_order_number") });
        if (question.answer == document.getElementById('answertextbox').value) {
            console.log('True');
            Questions.update(question._id, {$set: {text: question.text.substr(0, question.text.length - 1) + question.answer, player: Session.get("player_name")}});
            callGetNewQuestion();
        }
        else {
            console.log('False');
        }
        document.getElementById('answertextbox').value = "";
        document.getElementById('answertextbox').focus();
    }
});

callGetNewQuestion() 在客户端和服务器上都会触发:

getNewQuestion: function () {
    var nr1 = Math.round(Math.random() * 100);
    var nr2 = Math.round(Math.random() * 100);
    question_string = nr1 + " + " + nr2 + " = ?";
    question_answer = (nr1 + nr2);
    current_order_number = Questions.find({}).count() + 1;
    current_question_id = Questions.insert({ order_number: current_order_number, text: question_string, answer: question_answer });
    return Questions.findOne({_id: current_question_id});//current_question_id;
},

完整的源代码在这里供参考:https ://github.com/tomsoderlund/MathPlay

4

1 回答 1

3

Your problem lies with this:

callGetNewQuestion() triggers this on both client and server

This will generate a different _id because of the timing difference, as well as a different question which will then get replaced with that one that the server generated. However, this might not always be the case. This makes it very easy to let things get out of sync, simply because your client is generating its own stuff.


You'll need to figure out a better approach at making sure the client generates the same data as the server. Which can be done by making sure that a random number generator is seeded the same way and thus would give the same random numbers every time. This will resolve any flickering because the values are different.


Then, for the actual bug you might not want to do this:

return Questions.findOne({_id: current_question_id});

But do this instead (only on the client, do nothing on the server):

Session.set('current_order', current_order_number); // ORDER! Not the _id / question_id.

That way, you can put the following in a template helper:

return Questions.findOne({ order_number: Session.get('current_order') });

In essence, this will work in a reactive way on the Collection and not dependent on the return value.

于 2012-06-07T15:20:47.363 回答