Reputation: 103
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){
}).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
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)?
Upvotes: 0
Views: 1037
Reputation: 103
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);
});
Upvotes: 1
Reputation: 21926
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
});
Upvotes: 0
Reputation: 13662
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) {
});
});
Upvotes: 0