Reputation: 740
I'm not completely sure if the title correctly describes my problem. Please correct me if I'm wrong :)
I would like to call a function to update a user's data in multiple databases/Firebase authentication (the function then calls multiple other async functions). I would like to do all the error handling in the parent function which calls updateUserData()
. How can I do this?
This is my code:
async updateUserData(user: User) {
// Update Email
const currentUser = this.getCurrentUser();
if(user.email && user.email != currentUser?.email)
currentUser?.updateEmail(user.email)
// Update Display Name
if(user.displayName && user.displayName != currentUser?.displayName)
currentUser?.updateProfile({displayName: user.displayName})
// Update User DB
this.firestore
.collection('users')
.doc(user.uid)
.set(user, { merge: true })
// Update Public User DB
const publicUserDBRef = this.firestore.collection('public-users').doc(user.uid);
if(user.displayName && !user.settings.isPrivate) {
publicUserDBRef
.set({ uid: user.uid, displayName: user.displayName }, { merge: true })
} else {
publicUserDBRef
.delete()
}
}
I have tried using a try-catch
block, adding .catch( error => { throw new Error(error.code) })
to all the async functions in updateUserData()
, using return new Promise( (resolve, reject) => {...}
(resolve()
was called at the end of the function, after updating the Public User DB and reject was called in each .catch()
block)
Upvotes: 1
Views: 313
Reputation: 84982
.set
and .delete
return promises, but you're not doing anything with those promises. So neither this function, nor any function that calls this one will wait for them to finish. This also means a try/catch cannot catch any asynchronous errors they throw.
If you're ok with waiting for the first .set
to complete before the .delete
(or second set) happens, you just need to stick some await
s on your current code:
// Update User DB
await this.firestore
.collection("users")
.doc(user.uid)
.set(user, { merge: true });
// Update Public User DB
const publicUserDBRef = this.firestore.collection("public-users").doc(user.uid);
if (user.displayName && !user.settings.isPrivate) {
await publicUserDBRef.set(
{ uid: user.uid, displayName: user.displayName },
{ merge: true }
);
} else {
await publicUserDBRef.delete();
}
If you want both to happen in parallel, then I'd recommend creating an array of promises, then doing Promise.all with them, and either returning or awaiting that promise:
const promises = [];
// Update User DB
promises.push(
this.firestore.collection("users").doc(user.uid).set(user, { merge: true })
);
// Update Public User DB
const publicUserDBRef = this.firestore.collection("public-users").doc(user.uid);
if (user.displayName && !user.settings.isPrivate) {
promises.push(
publicUserDBRef.set(
{ uid: user.uid, displayName: user.displayName },
{ merge: true }
)
);
} else {
promises.push(publicUserDBRef.delete());
}
return Promise.all(promises);
Upvotes: 1
Reputation: 882
It is pretty simple, just add try catch around await
-ed function:
async function parentFunction() {
// Here was created user
try {
await updateUserData(user);
} catch (e) {
console.log(`e is ${e}`);
// Some handling of the error
}
// ...
}
Upvotes: 0