Search code examples
javascriptcloudparse-platformmbaas

Cloud code on parse.com skipping a save


I'm trying to set up a game that allows playing with random players. The code below is supposed to create a GameMessage object for both paired players. To relate both objects as part of the same game, I've decided to save the objectId of of the game made for "firstplayer" in the field "otherside" for "secondplayer" and vice-versa. For some reason (perhaps the first save of firstplayer and secondplayer isn't done before the code attempts to retrieve the objectIds, meaning there are no objectIds to get?).

Short version: Why are the "otherside" values not saving?

Parse.Cloud.define("findpartner", function(request, response) {

var User = Parse.Object.extend("_User");
var user = new User();

var currentuser = Parse.User.current();
currentuser.set("searching", 0);


var query = new Parse.Query(User);
query.equalTo("searching", 1);
query.limit(50); //limit to at most 50 users
query.find({
    success: function(objects) {
        var amount = objects.length;
        var indexNum = Math.floor((Math.random() * amount));
         var newpartner = objects[indexNum];
                   if (amount > 0 && newpartner.id !=currentuser.id) {



            newpartner.set("searching", 0);

            var Firstplayer = Parse.Object.extend("GameMessages");
            var firstplayer = new Firstplayer();

            var Secondplayer = Parse.Object.extend("GameMessages");
            var secondplayer = new Secondplayer();

            firstplayer.set("sender", currentuser.id);
            firstplayer.set("receiver", newpartner.id);
            firstplayer.set("sent",0);
            firstplayer.set("received",0);
            firstplayer.set("receiverName", newpartner.getUsername());

            secondplayer.set("sender", newpartner.id);
            secondplayer.set("receiver", currentuser.id);
            secondplayer.set("sent",0);
            secondplayer.set("received",0);
            secondplayer.set("receiverName", currentuser.getUsername());

            firstplayer.save().then(function(secondplayer){               <<<
                return secondplayer.save();                               <<<

                }).then(function(firstplayer_update) {                    <<<
                return firstplayer.save({ otherside: secondplayer.id});   <<<

            }).then(function(secondplayer_update){                        <<<
                return secondplayer.save({ otherside: firstplayer.id});   <<<

            });


            newpartner.save(null, {useMasterKey: true});

        }
                    else {
                        currentuser.set("searching", 1);
                    }
        currentuser.save();
        response.success(amount);
      },
    error: function(error) {
        alert("Error: " + error.code = " " + error.message);
      }
   });    

});

I added arrows to show where the "otherside" is. They're not in the actual code. I do not doubt the code has mistakes though, I do not know javascript. I wrote it solely by studying the parse.com documentation.


Solution

  • I'm not convinced that it makes sense to create these 2 independent messages and link them together, but I won't let that stand in the way of getting this working. This isn't tested, but I've refactored your code and think you should try to glean a few things from it.

    // Set this up once, outside of your function, and use it everywhere
    var GameMessage = Parse.Object.extend("GameMessages");
    
    Parse.Cloud.define("findpartner", function(request, response) {
    
        // Code defensively, make sure this function requires a user be logged in.
        if (!request.user) {
            console.log("non-user called findpartner");
            return response.error("Unauthorized.");
        }
    
        // Get the user who called the function
        var user = request.user;
        // The end response is a number, apparently
        var result = 0;
        // The target player
        var targetPlayer;
        // The two messages that will be used if a match is found
        var firstmsg = new GameMessage();
        var secondmsg = new GameMessage();
    
        // Create a Users query
        var query = new Parse.Query(Parse.User);
        query.equalTo("searching", 1);
        query.notEqualTo("objectId", user.id);
        query.limit(50);
        // Remove public access to Find operations for Users in the Data Browser
        // Use the master key to query, and use promise syntax.
        query.find({ useMasterKey: true }).then(function(objects) {
            result = objects.length;
            // If no users were found searching, mark the user as searching and save
            if (result == 0) {
                user.set('searching', 1);
                // Return the save promise
                return user.save(null, { useMasterKey: true });
            }
            // Pick a random user out of the response
            var indexNum = Math.floor((Math.random() * objects.length));
            var targetPlayer = objects[indexNum];
            // Set that user to no longer be searching and save
            targetPlayer.set("searching", 0);
            return targetPlayer.save(null, { useMasterKey: true }).then(function() {
    
                firstmsg.set("sender", user.id);
                firstmsg.set("receiver", targetPlayer.id);
                firstmsg.set("sent", 0);
                firstmsg.set("received", 0);
                firstmsg.set("receiverName", targetPlayer.getUsername());
    
                secondmsg.set("sender", targetPlayer.id);
                secondmsg.set("receiver", user.id);
                secondmsg.set("sent", 0);
                secondmsg.set("received", 0);
                secondmsg.set("receiverName", user.getUsername());
    
                // Return the promise result of saving both messages
                return Parse.Object.saveAll([firstmsg, secondmsg], { useMasterKey: true });
    
            }).then(function(messages) {
    
                // Set the pointers to reference each other
                firstmsg.set("otherside", secondmsg.id);
                secondmsg.set("otherside", firstmsg.id);
                // Return the promise result of saving both messages, again
                return Parse.Object.saveAll([firstmsg, secondmsg], { useMasterKey: true });
            });
        }).then(function() {
            // All the stuff above has finished one way or the other, now we just need to 
            // send back the result. 0 if no match was made.
            response.success(result);
        }, function(error) {
            response.error(error);
        });
    
    });