如何处理NodeJS中的嵌套Promises

时间:2018-11-14 11:46:43

标签: javascript node.js callback promise nested

我是Promises的新手,所以希望您能为我提供帮助。 我有以下代码:

bcrypt.genSalt(10)
    .then((salt) =>{
        return  bcrypt.hash(newUser.password, salt)
    })
    .then((hash)=>{
        newUser.password = hash;
        return mariaDB.pool.getConnection()
    })
    .then((conn)=>{
        conn.beginTransaction()
            .then() //here I'm doing some database request
            .catch((err)=>{
                console.log(err)
                return conn.rollback() //where is this Promise handled?
            })
    })
    .catch((err)=>{
        res.json({error: err})
    })

我收到一个newUser对象,该对象首先传递给bcrypt来加密我的密码。 然后,我需要对我的MariaDB数据库进行事务处理。但是这种“嵌套的承诺”正确吗?有更好的解决方案吗?承诺“ return conn.rollback”在哪里处理?

问候和感谢!

4 个答案:

答案 0 :(得分:1)

bcrypt.genSalt(10)
.then((salt) =>{
    return  bcrypt.hash(newUser.password, salt)
})
.then((hash)=>{
    newUser.password = hash;
    return mariaDB.pool.getConnection()
})
.then((conn)=>{
    return dbops(conn)
})
.catch((err)=>{
    res.json({error: err})
})

//添加了新功能db ops

function dbops(conn){
   return new Promise(function(resolve,reject){
       conn.beginTransaction()
          .then((data)=>{
            //db stuff
            resolve("db stuff done")
        }).catch((err)=>{
            console.log(err)
            conn.rollback()
            reject(err)
        })
     })}

希望这会对您有所帮助。

答案 1 :(得分:1)

像这样简单吗?

bcrypt.genSalt(10)
    .then(salt => bcrypt.hash(newUser.password, salt))
    .then(hash => {
        newUser.password = hash;
        return mariaDB.pool.getConnection()
    })
    .then(conn => {
       return conn.beginTransaction()
          .then(() => {
              // here I'm doing some database request
          })
          .catch( err => {
            conn.rollback();
            throw new Error(err); // this error will be cathed on bottom catch
          });
    })
    .catch(err => res.json({error: err}))

答案 2 :(得分:0)

return conn.rollback() //where is this Promise handled?

未处理,这是此代码段的问题。嵌套的Promise应该链接起来,以维持适当的控制流,即从thencatch回调返回:

.then((conn)=>{
    return conn.beginTransaction()
    ...

需要嵌套约定,因为conn回调中应有thenasync..await是更方便的处理方式,它可以展平嵌套的Promise:

try {
    const salt = await bcrypt.genSalt(10)
    const hash = await bcrypt.hash(newUser.password, salt)
    newUser.password = hash;
    const conn = await mariaDB.pool.getConnection()
    try {
        conn.beginTransaction()
        // ...
    } catch (err) {
        await conn.rollback()
    }
} catch (err) {
    res.json({error: err})
}

一件好事是在rollback之后抛出一个错误,因为很明显这时出错了。

答案 3 :(得分:0)

使用 async / await (通过摆脱所有嵌套的承诺使您的生活更加轻松,稍后再感谢我!)进行重写:

try {
  const salt = await bcrypt.genSalt(10);
  const hash = await bcrypt.hash(newUser.password, salt);
  newUser.password = hash;
  const conn = await mariaDB.pool.getConnection();
  try {
    const transaction = await conn.beginTransaction();
    // your db calls
  } catch (err) {
    console.log(err);
    return conn.rollback();
  }
} catch (err) {
  res.json({error: err})
}

请确保将此块包装在async函数中。例如,对于自调用功能,请使用:

(async() => {
 // the block of code using await ...
})();