Because .findOne
already returns a Promise
, there's no need to construct a new one with new Promise
- instead, just chain onto the existing Promise
chain with .then
and .catch
as needed. Such Promise
chains can have any number of .then
s and .catch
s - just because you consume a Promise
with one .then
doesn't prevent you from using the same resolve value elsewhere. To illustrate:
makePromise()
.then((result) => {
console.log(result);
// Returning inside a `.then` will pass along the value to the next `.then`:
return result;
})
.then((result) => {
// this `result` will be the same as the one above
});
In other words - there's no need to construct a new Promise
every time you want to be able to use another .then
. So:
Then I won't probably be able to .then and .catch in findUserByEmail("[email protected]")
isn't correct - you can indeed chain onto the end of an existing Promise with as many .then
s and .catch
es as you want.
Note that a .then
which only returns its parameter and does nothing else (such as .then(currentUser => currentUser)
) is superfluous - it won't do anything at all. Also note that a .catch
will catch Promise rejections and resolve to a resolved Promise
. So if you do
function findUserByEmail(email) {
return User.findOne({email: email})
.then(currentUser => currentUser)
.catch(error => error)
}
that catch
means that callers of findUserByEmail
will not be able to catch
errors, because any possible errors were caught in findUserByEmail
's catch
. Usually, it's a good idea to allow errors to percolate up to the caller of the function, that way you could, for example:
someFunctionThatReturnsPromise('foobar')
.then((result) => {
// everything is normal, send the result
res.send(result);
})
.catch((err) => {
// there was an error, set response status code to 500:
res.status(500).send('there was an error');
})
So, unless your findUserByEmail
or createNewUser
helper functions need to do something specific when there's an error, it would probably be best just to return the Promise
alone:
const findUserByEmail = email => User.findOne(email);
const createNewUser = newUserDetails => new User(newUserDetails).save();
If your helper functions do need to do something when there's an error, then to make sure that the error gets passed along properly to the caller of the function, I'd recommend either throwing the error inside the catch
:
const findUserByEmail = email => User.findOne(email)
.catch((err) => {
// error handling - save error text somewhere, do a console.log, etc
throw err;
});
so that you can catch
when something else calls findUserByEmail
. Otherwise, if you do something like
const findUserByEmail = email => User.findOne(email)
.catch((err) => {
// do something with err
return err;
});
then the caller of findUserByEmail
will have to check inside the .then
if the result is actually an error, which is weird:
findUserByEmail('[email protected]')
.then((result) => {
if (result instanceof Error) {
// do something
} else {
// No errors
}
});
Better to throw the error in findUserByEmail
's catch
, so that the consumer of findUserByEmail
can also .catch
.