Reputation: 309
I'm, relatively new to Promises, so I hope you can help me. I have the following code:
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})
})
I receive a newUser object, which I first pass to bcrypt to encrypt my password. Then I need to make a transaction to my MariaDB database. But is this kind of "nested Promises" correct? Is there a better solution? Where is the promise "return conn.rollback" handled?
Greetings and Thanks!
Upvotes: 0
Views: 210
Reputation: 5698
Do it simple like this:
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}))
Upvotes: 2
Reputation: 7232
A rewrite with async/await (making your life easier by getting rid of all those nested promises, thank me later!) would look like this:
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})
}
Please make sure you wrap this block within an async
function. For example, for self-invoking function use:
(async() => {
// the block of code using await ...
})();
Upvotes: 0
Reputation: 223114
return conn.rollback() //where is this Promise handled?
is not handled, this is the problem with this snippet. Nested promises should be chained in order to maintain proper control flow, i.e. returned from then
and catch
callbacks:
.then((conn)=>{
return conn.beginTransaction()
...
Nested promise is required because conn
should be available in then
callbacks. A more convenient way to handle this is async..await
, this allows to flatten nested promises:
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})
}
A good thing would be to rethrow an error after rollback
because it's clear that things went wrong at this point.
Upvotes: 0
Reputation: 633
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})
})
// added new function 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)
})
})}
Hope this will help you.
Upvotes: 1