简体   繁体   中英

On Meteor, a function with $inc: is being called twice, when I am attempting to only call it once

I have a game in which two people play against each other. After the clock runs down I call the function below, which is supposed to increase the current question by 1. However, it increases it by 1 TWICE.

increaseQuestion: function() {
    GameCollection.update({current:true}, { $inc: { currentQuestion: 1}});
},

Here is specifically the code where it is called:

Template.gamePage.clock = function () {
    var game = GameCollection.findOne({current: true});
    var currentQuestion = game.currentQuestion;
    var question = game.gameQuestions[currentQuestion];
    var clockQuestion = Clocks.findOne({gameId: game._id, questionId: question._id});
    var clock = clockQuestion.clock;

    if(clock === 0) {
        Meteor.call('increaseQuestion');
    } else {
        Meteor.call('windDown', clockQuestion, clock);
    }

    // format into M:SS
    var min = Math.floor(clock / 60);
    var sec = clock % 60;
    return min + ':' + (sec < 10 ? ('0' + sec) : sec);
};

Here is the method within the code above (which could be causing problems)

Meteor.methods({
    windDown: function(clockQuestion, clock) {
        var interval = Meteor.setInterval(function () {

            clock -= 1;

            Clocks.update(clockQuestion._id, {$set: {clock: clock}});

            // end of game
            if (clock === 0) {
                // stop the clock
                Meteor.clearInterval(interval);
                // declare zero or more winners

            }
        }, 1000);
    }
});

Why is the function being called twice? I tried moving the method from both client and server folder to a server only folder and it is still called twice.

I'm surprised it's only being called twice, to be honest.

The clock helper has a dependency on the ClockQuestion document which has the same gameId as the current game. However, when that helper is run, the windDown method is called, which is going to update that ClockQuestion document, which is going to cause the helper to be reactively rerun, which is going to call the windDown method again, etc...

To be honest, this sort of control logic really should not be included in a helper function for exactly this reason - it's going to be impossible to control. windDown needs to be called by whatever it is that's making the gamePage template render in the first place, or else a Deps.autorun block, the reactivity of which you can have much more control over, as opposed to a reactive UI element which is (by design) being managed by Meteor rather than your own app explicitly.

My suspicion is this: Template.gamePage.clock uses GameCollection , so when that collection is updated, then the function will be re-run reactively.

Since increaseQuestion doesn't depend on any arguments from the client, why not just move it to the // end of game if block in windDown ?

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