Matt Matt - 3 months ago 47
Javascript Question

How do you prevent nested queries/catches in sequelize?

I think I'm preventing nested queries as much as possible, but I'm honestly not sure. I understand the calls here can all be executed in a single select query, but I did this to simplify the example.

// This example is in TypeScript

// find user
User.find({where:{username:'user'}})

// if found user
.then(function(user) {

return User.find({where:{username:'other_user'}})

// if found other_user
.then(function(other_user) {
// do stuff
return whatever_i_need
}

// if something went wrong, go straight to parent catch
.catch(function(err) {
// do stuff
throw new Error()
}
}

// if previous .then() returned success
.then(function(data) {

return User.find({where:{username:'yet_another_user'}})

// if found yet_another_user
.then(function(yet_another_user) {
// do stuff
return whatever_i_need_again
}

// if something went wrong, go straight to parent catch
.catch(function(err) {
// do stuff
throw new Error()
}
}

// if anything threw an error at any point in time
.catch(function(err) {
// handle the error
}


However, this results in nested promises, which is exactly what promises are meant to prevent. Is this the "max depth" recommended for promises, or am I missing something? Is there a better way to chain queries?

Answer

Return the nested promise instead of handle it in the inner blocks to flatten the structure.

User.find({where:{username:'user'}})
.then(function(user) {
  if (user) { // if found user
    // do stuff
    return User.find({where:{username:'other_user'}});
  }
  throw new Error('user not-found');
})
.then(function(other_user) {
  if (other_user) { // if found other_user
    // do stuff
    return whatever_i_need;
  }
  throw new Error('other_user not-found');
})
.then(function(data) {
  return User.find({where:{username:'yet_another_user'}})
})
.then(function(yet_another_user) {
  if (yet_another_user) { // if found yet_another_user
    // do stuff
    return whatever_i_need_again;
  }
  throw new Error('yet_another_user not-found');
}
.then(function(data){
  // do stuff
})
.catch(function(err) { // if anything threw an error at any point in time
  // handle the error
}

Note that a resolved promise means a query is successfully done, and that's it. A successful query does't guarantee results to be returned. Empty result is a valid outcome of resolved promises.

Note also that the return value from a resolve or reject callback will be wrapped with a resolved promise, and then passed to the next then block, making a meaningful promise chain. Thanks for @Matt's follow-up feedback below regarding this point.