Reputation: 159
I'm new to Parse and trying to wrap my head around promises at the same time. What I'd like to do is simply create a user in the DB if one doesn't exist and if one does exist I would update the row. The problem I am having is that my Parse.Query never finds the user row and then when it fails to find the row, it then fails to create a new user because the row exists. I know this is because either I need to force the method to wait for the search to return or to return a promise to be executed when the query returns, but I cannot figure out how to do it.
My current code is:
Parse.Cloud.define("findUser2", async req => {
var phoneNumber = req.params.phoneNumber;
phoneNumber = phoneNumber.replace(/\D/g, '');
console.log("Incoming phone number is: " + phoneNumber)
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo('username', phoneNumber);
var user = await userQuery.first();
if(user) {
console.log("Found a user, user is: " + user);
//Validation stuff goes here
} else {
console.log("Did not find a user, create and return it");
var newUser = new Parse.User();
newUser.setUsername(phoneNumber);
newUser.setPassword(secretPasswordToken + phoneNumber);
newUser.set("language", "en");
newUser.setACL({});
newUser.save();
//If this is not commented out, fails with:
//Error: Cannot create a pointer to an unsaved ParseObject
//user = newUser;
}
console.log("about to return the user");
return user;
});
The output then returns:
app[web.1]: Incoming phone number is: 5555551212
app[web.1]: Did not find a user, create and return it
app[web.1]: about to return the user
app[web.1]: info: Ran cloud function findUser2 for user undefined with:
app[web.1]: Input: {"phoneNumber":"5555551212"}
app[web.1]: Result: undefined {"functionName":"findUser2","params":{"phoneNumber":"5555551212"}}
app[web.1]: error: Parse error: Account already exists for this username. {"code":202,"stack":"Error: Account already exists for this username.\n at /app/node_modules/parse-server/lib/RestWrite.js:567:13\n at processTicksAndRejections (internal/process/task_queues.js:85:5)"}
app[web.1]: (node:23) UnhandledPromiseRejectionWarning: Error: Account already exists for this username.
Based on the ordering of the logs, I know it is exiting the function before it completes the query. I thought the await
would force it to not continue until this query returns or times out, thereby being able to fulfill the promise. It seems like I am wrong though and I am unsure how to resolve the issue.
Ideally I'd use Promises because I'd allow my code to run more efficiently, but I have await in for now because I was hoping it would make it simpler to get it working and be fine for a prototype. I'm looking for a good path forward and if the right approach is to return a promise, I'd like to know.
Upvotes: 0
Views: 165
Reputation: 2984
Your cloud code function is returning before the new user is actually saved. You just need to await
for it before returning. It would be something like this:
Parse.Cloud.define("findUser2", async req => {
var phoneNumber = req.params.phoneNumber;
phoneNumber = phoneNumber.replace(/\D/g, '');
console.log("Incoming phone number is: " + phoneNumber)
var userQuery = new Parse.Query(Parse.User);
userQuery.equalTo('username', phoneNumber);
var user = await userQuery.first({ useMasterKey: true });
if(user) {
console.log("Found a user, user is: " + user);
//Validation stuff goes here
} else {
console.log("Did not find a user, create and return it");
var newUser = new Parse.User();
newUser.setUsername(phoneNumber);
newUser.setPassword(secretPasswordToken + phoneNumber);
newUser.set("language", "en");
newUser.setACL({});
await newUser.save(); //This is the line you need to change
//If this is not commented out, fails with:
//Error: Cannot create a pointer to an unsaved ParseObject
//user = newUser;
}
console.log("about to return the user");
return user;
});
Upvotes: 1