Home > Net >  javascript promises inside then
javascript promises inside then

Time:10-07

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:

  1. 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.

  1. 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            
  • Related