I've recently discovered the promises, and they made my life much easier. But there is a specific case that I'm not being capable to handle. It is when I have to call a promise inside then().
Here is my code:
const firebaseAuth = require("firebase/auth");
const auth = firebaseAuth.getAuth();
const { User } = require('../models/User');
app.post('/create_user', (req, res) => {
user_uid = req.body.params.uid;
newUserEmail = req.body.params.email;
newUserPassword = req.body.params.password;
let user;
firebaseAuth.createUserWithEmailAndPassword(auth, newUserEmail, newUserPassword)
.then((userCredential) => new Promise((resolve, reject) => {
if(userCredential == undefined) throw Error("createUserWithEmailAndPassword failed");
user = new User(userCredential.user.uid, req.body.params.userAttributes);
resolve()
}))
.then(firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null))
.then(/*other functions using User object*/)
.then(() => { // finished promise chaining
res.status(200).send();
})
.catch((e) => {
console.log(e)
res.status(403).send();
})
});
The problem is, the .then(firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null))
is being called before the user is initialized in user = new User(userCredential.user.uid, req.body.params.userAttributes);
.
Could someone please help me understand why is this happening? And in case I have to call a promise inside a then(), Do I also have to nest a .catch()? Or my single .catch() at the end of my function will be capable to handle possible errors?
Edit: User does some async tasks inside the constructor, because it has to handle the images.
And I can only Initialize it, after firebaseAuth.createUserWithEmailAndPassword(auth, newUserEmail, newUserPassword)
because I have to get the generated Id in userCredential
CodePudding user response:
I see two issues here:
- The most simple fix for your code is to change this line:
.then(firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null))
to
.then(() => firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null))
notice the the the arrow function wrapping the call to firebaseAuth
, before your code was the equivalent of asking firebaseAuth
to return a function that would handle that step of the promise chain.
- If the only purpose of
return new Promise()
is to do the validation and get the user, you can simply.
.then((userCredential) => {
if(userCredential == undefined) throw Error("createUserWithEmailAndPassword failed");
return new User(userCredential.user.uid, req.body.params.userAttributes);
})
and the user will be available in the next chain as
.then(user => {
// do stuff with user
})
CodePudding user response:
You can use async
function and try
block to await
the userCredential value like this:
app.post('/create_user', async(req, res) => {
user_uid = req.body.params.uid;
newUserEmail = req.body.params.email;
newUserPassword = req.body.params.password;
let user;
try {
const userCredential =
await firebaseAuth.createUserWithEmailAndPassword(
auth,
newUserEmail,
newUserPassword
);
if (userCredential == undefined)
return res
.status(400)
.send('❌ CreateUserWithEmailAndPassword failed