0

I am developing an app in Parse and I'm trying to understand promises. I'm not finding very many working examples other than the very simple ones here: https://parse.com/docs/js/guide.

I'm querying the _User table. Then I loop through the users in an _.each loop. I'm running 2 cloud functions inside the loop for each iteration. At what point do I create the promise? Do I create one for each cloud function success within the loop? Or do I push each success return value onto an array and make that the promise value outside of the loop? I've tried both but I can't figure out the correct syntax to do either, it seems.

I'll break it down in pseudo-code because that may be easier than actual code:

var query = new Parse.Query(Parse.User); query.find().then(function(users){

  • loop through each user in an _.each loop and run a cloud function for each that returns a number.
  • If the number > 0, then I push their username onto array1.
  • Then I run a 2nd cloud function on the user (still within the _.each loop) that returns a number.
  • If the number > 0, then I push their username onto array2.

}).then(function(promisesArray){

// I would like "promisesArray" to either be the 2 arrays created in the preceding section, or a concatenation of them.

// Ultimately, I need a list of usernames here. Specifically, the users who had positive number values from the cloud functions in the preceding section

  • concatenate the 2 arrays, if they're not already concatenated
  • remove duplicates
  • send push notifications to the users in the array });

Questions: - At what point do I create & return promises & what syntax should I use for that? - Should .then(function(promisesArray){ be .when(function(promisesArray){ (when instead of then)?

3 Answers 3

1

Thank you both for your ideas! This is what ultimately worked:

var query = new Parse.Query(Parse.User);
query.find().then(function(users){
  var allPromises = [];
  var promise1, promise2;

  _.each(users, function(user){
    if(user.get("myvalue") != "undefined" && user.get("myvalue") != ""){
      promise1 = Parse.Cloud.run("getBatch1", {param1: param1value, param2: param2value})
      .then(function(numResult){
        if(Number(numResult) > 0){
          return Parse.Promise.as(user.getUsername());
        }
      });
    }
    allPromises.push(promise1);

    if(user.get("anothervalue")==true){
      promise2 = Parse.Cloud.run("getBatch2", {param1: param1value, param2: param2value})
      .then(function(numResult2){
        if(Number(numResult2) > 0){
          return Parse.Promise.as(user.getUsername());
        }
      });
    }
    allPromises.push(promise2);
  });

  // Return when all promises have succeeded.
  return Parse.Promise.when(allPromises);

}).then(function(){
  var allPushes = [];
  _.each(arguments, function(pushUser){
    // Only add the user to the push array if it's a valid user & not already there.
    if(pushUser != null && allPushes.indexOf(pushUser) === -1){
      allPushes.push(pushUser);
    }      
  });

  // Send pushes to users who got new leads.
  if(allPushes.length > 0){
    Parse.Push.send({
      channels: allPushes,
      data: {
        alert: "You have new leads."
      }
    }, {
      success: function () {
        response.success("Leads updated and push notifications sent.");
      },
      error: function (error) {
        console.log(error);
        console.error(error);
        response.error(error.message);
      }
    });
  }
  response.success(JSON.stringify(allPushes));

}, // If the query was not successful, log the error
function(error){
  console.log(error);
  console.error(error);
  response.error(error.message);
});
Sign up to request clarification or add additional context in comments.

Comments

0

I'm not familiar with Parse API but I'd do it this way. Of course, I can't test my code so tell me if it works or not:

var query = new Parse.Query(Parse.User);
query.find()
    .then(function(users) {
        var promises = [];
        users.forEach(function(user) {
            // the first API call return a promise so let's store it
            var promise = cloudFn1(user)
                .then(function(result) {
                    if (result > 0) {
                        // just a way to say 'ok, the promise is resolved, here's the user name'
                        return Parse.Promise.as(user.name);
                    } else {
                        // return another promise for that second API call
                        return cloudFn2(user).then(function(res) {
                            if (result > 0) {
                                return Parse.Promise.as(user.name);
                            }
                        });
                    }
                });

            // store this promise for this user
            promises.push(promise);
        });

        // return a promise that will be resolved when all promises for all users are resolved
        return Parse.Promise.when(promises);
    }).then(function(myUsers) {
        // remove duplicates is easy with _
        myUsers = _.uniq(myUsers);
        // do your push
        myUsers.forEach( function(user) {

        });
    });

Comments

0

First, you need to understand what Promises are. From what I understand of what you're trying to do it should look something like this:

//constructs the Parse Object
var query = new Parse.Query(Parse.User);

//find method returns a Promise
var res   = query.find()

//good names will be a Promise of an array of usernames
//whose value is above 0
var goodNames = res
    .then(function(data) {

        //assumes the find method returns an array of
        //objects, one of the properties is username
        //we will map over it to create an Array of promises
        //with the eventual results of calling the AJAX fn
        var numberPromises = data.map(function(obj) {

            //wrap the call to the cloud function in a new
            //promise
            return new Promise(resolve, reject) {
                someCloudFn(obj.username, function(err) {
                    if (err) {
                        reject(err);
                    } else {
                        resolve(num);
                    }
                });
            }
        };

        //Promise.all will take the array of promises of numbers
        //and return a promise of an array of results
        return [data, Promise.all(numberPromises)];
    })
    .then(function(arr) {

        //we only get here when all of the Promises from the
        //cloud function resolve
        var data    = arr[0];
        var numbers = arr[1];
        return data
            .filter(function(obj, i) {

                //filter out the objects whose username number
                //is zero or less
                return numbers[i] > 0;
            })
            .map(function(obj) {

                //get the username out of the query result obj
                return obj.username;
            });
    })
    .catch(function(err) {
        console.log(JSON.stringify(err));
    });

Now whenever you need to use the list of usernames whose number isn't zero you can call the then method of goodNames and get the result:

goodNames.then(function(listOfNames) {
    //do something with the names
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.