NodeJS javascript承诺在then里面

vhmi4jdf  于 2022-12-18  发布在  Node.js
关注(0)|答案(3)|浏览(140)

我最近发现了承诺,它们让我的生活轻松了很多。但是有一个特殊的情况我没有能力处理。那就是当我不得不在then()里面调用承诺的时候。
下面是我的代码:

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();
    })
});

问题是,在user = new User(userCredential.user.uid, req.body.params.userAttributes);中初始化用户之前,.then(firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null))被调用了。有人能帮助我理解为什么会发生这种情况吗?如果我必须在then()中调用一个promise,我是否也必须嵌套一个.catch()?或者我在函数末尾的单个.catch()将能够处理可能的错误?
编辑:用户在构造函数内部执行一些异步任务,因为它必须处理图像。我只能在firebaseAuth.createUserWithEmailAndPassword(auth, newUserEmail, newUserPassword)之后初始化它,因为我必须在userCredential中获得生成的Id

vybvopom

vybvopom1#

我在这里看到两个问题:
1.最简单的代码修复方法是更改以下行:

.then(firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null))

.then(() => firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null))

请注意,在您的代码相当于要求firebaseAuth返回一个处理承诺链中该步骤的函数之前,arrow函数 Package 了对firebaseAuth的调用。
1.如果return new Promise()的唯一目的是进行验证并获取用户,则可以简单地。

.then((userCredential) => {
   if(userCredential == undefined) throw Error("createUserWithEmailAndPassword failed");
    return new User(userCredential.user.uid, req.body.params.userAttributes);
  })


并且用户将在下一个链中可用,

.then(user => {
  // do stuff with user
})
ldioqlga

ldioqlga2#

您可以使用async函数和try块来awaituserCredential值,如下所示:

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 🙁');

    user = new User(
      userCredential.user.uid,
      req.body.params.userAttributes
    );

    await firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null);

    return res.status(201).send('Created!! 😀');
  } catch (error) {
    console.log('❌ Error:', error);
    return res.status(400).json({
      message: error,
    });
  }
});
1u4esq0p

1u4esq0p3#

我们永远不会发现new Promise() Package 了一个已经创造了承诺的库。
还要记住,链的形式是......

// promiseA, promiseB & promiseC are expressions that evaluate to promises
return promiseA.then(resolutionOfPromiseA => {
  // synchronous work
  return promiseB;
}).then(resolutionOfPromiseB => {
  // synchronous work
  return promiseC;
}).catch(error => {})

在更新的语法中:

async function myFunction() {
  try {
    let resolutionOfPromiseA = await promiseA;
    // synchronous work
    let resolutionOfPromiseB = await promiseB;
    // synchronous work
    return promiseC;
  } catch(error) {
  }

坚持OP的旧语法风格(只要保持一致就很好)

let user;
 firebaseAuth.createUserWithEmailAndPassword(auth, newUserEmail, newUserPassword)
 .then(userCredential => {
     // note that we don't create a promise
     if(userCredential == undefined) throw Error("createUserWithEmailAndPassword failed");
     user = new User(userCredential.user.uid, req.body.params.userAttributes);
     // note that we return this one. It's good form, even if the next then doesn't use the result
     return firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null)
  })
 .then(res => {   // this res is the result of firebaseAuth.sendPasswordResetEmail
   // user is in scope here because it's in the containing scope
   /* other functions using User object */
 })
 .then(() => {                  // finished promise chaining
    res.status(200).send();
 })
 .catch((e) => {
    console.log(e)
    res.status(403).send();
})

edit如果你真的希望usersendPasswordReset之后的块中,并且你真的不想在包含作用域中保留用户变量,你可以说...

// move let declaration here
  let user = new User(//...

  // string an extra return user here
  // some linters think this is a faux pas
  return firebaseAuth.sendPasswordResetEmail(auth, user.attr.email, null)
    .then(() => return user)
)}.then(user =>

相关问题