0

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.

SMD01
  • 101
  • 1
  • 13
  • Interesting ... I'm going to put together an answer with revised code and probably a different approach. – Fosco Jul 11 '14 at 20:54

2 Answers2

0
        firstplayer.save();
        secondplayer.save();

        secondplayer.set("otherside",firstplayer.id);     <<<
        firstplayer.set("otherside",secondplayer.id);     <<<

        firstplayer.save();
        secondplayer.save(); 

This is the part of code that you say not working. In parse doc you can see that .save() is a non blocking operation. Means the line firstplayer.save() goes immediately to next line(it wont block the thread for saving). So when you set id secondplayer.set("otherside",firstplayer.id) firstplayer.id is still undefined.

So if you want a synchronous logic, like save first_object then save second_object , you have to use call backs.

first_object.save({
    success: function(saved_first_object) {
       second_object.save({
          success: function(saved_second_object) {
             //process complete
          },
          failure: function(error){

          }
       })
    },
    failure: function(error) {
       console.log(error);
    } 

})

You can also approach it using promises. http://blog.parse.com/2013/01/29/whats-so-great-about-javascript-promises/

UPDATE: Based on question edit from OP trying promises

Try this

            firstplayer.save()
            .then(function(saved_firstPlayer){
            firstplayer = saved_firstPlayer;               
            return secondplayer.save();                               

            }).then(function(saved_secondplayer) {
                 secondplayer = saved_secondplayer;                    
                 return firstplayer.save({ otherside: secondplayer.id});   

           }).then(function(updated_firstplayer){ 
               firstplayer = updated_firstplayer;                       
               return secondplayer.save({ otherside: firstplayer.id}); 

           }).then(function(updated_secondlayer){ 
              secondplayer= update_secondplayer;
           });
Subin Sebastian
  • 10,870
  • 3
  • 37
  • 42
0

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);
    });

});
Fosco
  • 38,138
  • 7
  • 87
  • 101
  • Worked great! Just the last parenthesis at line 70 "}).then(function(messages)) {" needed to be removed. That saveAll method is nice! Must've missed that.. And the reason I have it set up as 2 messages is that each player uploads a file and some strings to be downloaded by their partner. I figured it'd be easier to have 2 messages than to store all the files and strings in one object and try to differentiate who receives what. – SMD01 Jul 11 '14 at 21:48