Reputation: 6795
I have a Parse
CloudCode
beforeSave
function, which roughly does the following:
response.success()
, which means the code can go ahead and allow saving the new user;existing user
, fetch a group
object and add the existing user
to the group
.For this purpose, I am using chained promises to make the code cleaner. The code is below:
Parse.Cloud.beforeSave("Contact", function(request, response) {
var facebookID = request.object.get("facebookID");
var email = request.object.get("email");
var queryFb;
if (facebookID) {
queryFb = new Parse.Query(Parse.User);
queryFb.equalTo("facebookID", facebookID);
}
var queryEmail;
if (email) {
queryEmail = new Parse.Query(Parse.User);
queryEmail.equalTo("email", email);
}
var query;
if (facebookID && email) {
query = new Parse.Query.or(queryFb, queryEmail);
} else if (facebookID) {
query = queryFb;
} else {
query = queryEmail;
}
var user;
query.first().then(function(user) {
if (!user) {
response.success();
} else {
var groupQuery = new Parse.Query("Group");
groupQuery.equalTo("title", "ssAll");
groupQuery.equalTo("owner", request.user);
return groupQuery.first();
}
}).then(function(group) {
group.addUnique("contacts", user);
return group.save();
}).then(function(success) {
response.error("NOT ERROR - new object was NOT created");
}, function(error) {
response.error(error);
});
});
In my test case, the query returns !user
, so the response.success()
message is called - all good. However, this response seems to then travel down the promise chain, which is intended for the case when the query returns a user
object. And so, my function terminates with an error on line group.addUnique("contacts", user);
because, obviously, the group
object is undefined
.
How do I work around this issue?
Upvotes: 0
Views: 146
Reputation: 11297
The problem is that you are always resolving the first promise regardless of whether checking for the user was successful (no such user yet) or not. However, actually you don't ever have to resolve the promise. I suggest you separate the error case like this:
query.first().then(function(user) {
if (!user) {
response.success();
} else {
addUserToGroup(request.user).then(function() {
response.error("NOT ERROR - new object was NOT created");
}, function(error) {
response.error(error);
});
}
});
function addUserToGroup(user) {
var groupQuery = new Parse.Query("Group");
groupQuery.equalTo("title", "ssAll");
groupQuery.equalTo("owner", user);
return groupQuery.first().then(function(group) {
group.addUnique("contacts", user);
return group.save();
});
}
As you can see, the first promise doesn't ever have to be resolved because the result is not used anyway.
Upvotes: 1
Reputation: 62686
The code needed a few improvements. The key improvement was to provide consistent starting conditions to the second promise's resolution (the second then
block). The OP code called response.success() in the case where there was no existing user. This is fine, except the execution still falls through to the next resolution, in one case with an undefined group
parameter.
The new code fixes that by returning either the existingUser
(after the group has been updated) or null
. Null tells the next promise resolution to call success()
and allow the save to proceed, otherwise, block the save.
Also note, it is a mistake for the first block's user
parameter to conflict with the var user
in the enclosing scope. I tried to use variable naming below to highlight the two different types of users the code considers...
Parse.Cloud.beforeSave("Contact", function(request, response) {
var facebookID = request.object.get("facebookID");
var email = request.object.get("email");
// moved into a function so we can test and deal with it tersely
findUserByEmailOrFB(email, facebookID).then(function(existingUser) {
return (existingUser)? addContactToGroupOwnedBy(request.user, existingUser) : null;
}).then(function(existingUser) {
if (existingUser) {
response.error("NOT ERROR - new object was NOT created");
} else {
response.success();
}
}, function(error) {
response.error(error);
});
});
// find the group owned by ownerUser, add contactUser to its contacts return a promise fulfilled as contactUser
function addContactToGroupOwnedBy(ownerUser, contactUser) {
var groupQuery = new Parse.Query("Group");
groupQuery.equalTo("title", "ssAll");
groupQuery.equalTo("owner", ownerUser);
return groupQuery.first().then(function(group) {
group.addUnique("contacts", contactUser);
return group.save().then(function() { return contactUser; });
});
}
function findUserByEmailOrFB(email, facebookID) {
var queryFb;
if (facebookID) {
queryFb = new Parse.Query(Parse.User);
queryFb.equalTo("facebookID", facebookID);
}
var queryEmail;
if (email) {
queryEmail = new Parse.Query(Parse.User);
queryEmail.equalTo("email", email);
}
var query;
if (facebookID && email) {
query = new Parse.Query.or(queryFb, queryEmail);
} else if (facebookID) {
query = queryFb;
} else {
query = queryEmail;
}
return query.first();
}
Upvotes: 1