0

I'm new to Promises with Parse Cloud Code and I'm having some difficulty figuring out why my inner promise is not correctly firing. I get all the way through majority of my promises, but it's not getting to the comment. Is there something I'm missing, or did I not structure this correctly?

You'll see where it breaks down in the comment, but it should get a user for each of the IDs in the array and then send the SMS message.

I based my code on the following topic: https://www.parse.com/questions/executing-query-within-promisethen-block

app.post('/send_sms_group', function(req, res) {

    var to_group = req.body.to;
    var from = req.body.from;
    var message = req.body.message;

    var Groups = Parse.Object.extend("Groups");
    var query = new Parse.Query(Groups);
    query.get(to_group).then(function(group){
        return group;
    }).then(function(group){
        var groupOwner = group.get("groupOwner");
        var members = group.get("members");
        var promise = Parse.Promise.as();
        for (i=0; i<members.length; i++) 
        {
            var memberId = members[i];
            if(memberId != groupOwner.id){
                promise = promise.then(function(){
                    var findUser = new Parse.Query(Parse.User);
                    findUser.get(memberId).then(function(participant){
                        // Not getting here
                        console.log(participant);
                        if(participant.get('phone')){
                            console.log(participant.get('phone'));
                            if(!participant.get('isClaimed')){
                                console.log(participant.get('isClaimed'));
                                twilio_client.sendSms({
                                    to:participant.get('phone'), 
                                    from:from, 
                                    body:message
                                  }, function(err, responseData) {
                                    console.log(responseData);
                                    return responseData;
                                  }
                                );
                            }
                        }
                    });
                });
            }
        }
        return promise;
    }).then(function(){
        res.json(200, {"status":"success"});      
    }, function(error) {
        console.log(error);
        res.json(400,error);
    });
});
Jake Lisby
  • 494
  • 5
  • 21
  • Add a catch listener to see if you have any errors in your code. – Benjamin Gruenbaum Jul 29 '15 at 16:56
  • I'm still trying to help, but the first `.then(function(group){return group;})` is unecessary – gfpacheco Jul 29 '15 at 17:01
  • You should return the result of findUser.get(memberId), which is a promise itself. That is `return findUser.get(memberId).then(function(participant){` – xissburg Jul 29 '15 at 17:18
  • Holy smokes that was it! Thanks xissburg! Also, thanks for the help gfpacheco and Benjamin, I modified with both of your answers as well to clean up my code. – Jake Lisby Jul 29 '15 at 17:23
  • a) you are missing a few `return` statements in those callbacks - you always will need to return promises from asynchronous function b) you've fell for the classical [closure in a loop](http://stackoverflow.com/q/750486/1048572) mistake – Bergi Jul 29 '15 at 19:09
  • Take a look at my answer below for a more readable code, you may want to change your code for better maintainability – gfpacheco Jul 29 '15 at 21:07

1 Answers1

1

I'm still trying to understand the details of your code. But I think you want to:

  • Get the users group
  • Remove the group owner from the users ids
  • Get the users
  • Remove users that don't have phone or "are claimed"
  • Send an sms to the filtered list

And looks like your members field is an array of strings, not an array of pointers.

Take a look at this and try to understand what's happening:

app.post('/send_sms_group', function(req, res) {
  var to_group = req.body.to;
  var from = req.body.from;
  var message = req.body.message;

  // Get the group
  var groupQuery = new Parse.Query(Groups);
  groupQuery.get(to_group)
  .then(function(group) {
    var owner = group.get('groupOwner'),
        userIds = group.get('members'),
        usersQuery = new Parse.Query(Parse.User);

    // Remove the group owner
    userIds = userIds.filter(function(user) {
      return user !== owner.id;
    });

    // Get the users
    usersQuery.containedIn('objectId', userIds);
    return usersQuery.find();
  })
  .then(function(users) {
    // Remove users without phone or "are claimed"
    users = users.filter(function(user) {
      return user.get('phone') && !user.get('isClaimed');
    });

    // Send SMS for each user
    var smsPromises = users.map(function(user) {
      return twilio_client.sendSms({
        to: user.get('phone'),
        from: from,
        body: message
      };
    });

    return Parse.Promise.when(smsPromises);
  })
  .then(function() {
    res.json(200, {'status': 'success'});
  }, function(err) {
    console.error(err);
    res.json(400, err);
  });
});
gfpacheco
  • 2,831
  • 2
  • 33
  • 50
  • Marking this correct, because it works a lot quicker and more efficient for sure. There are a few errors in it I had to fix that I list below for others who might come along later: Change to usersQuery.containedIn("objectId",userIds); – Jake Lisby Aug 06 '15 at 02:16
  • Right, I updated the answer with the fix. I actually didn't test the code, is there anything else you had to do before it work? – gfpacheco Aug 06 '15 at 04:10