Reputation: 848
Hi I am trying to check for invalid cases before executing a database action. For some reason my code will run reject('Invalid E-mail address.');
but then it will also continue to run the await User.findOne({email})
line. There are several ways I can rewrite this but I would like to keep the current structure of this code. How can I terminate the function after reject and prevent the rest of the code from running? Thanks
user.database.ts
export const registerUser = async (email: string, password: string): Promise<User> => {
return new Promise(async (resolve, reject) => {
// check if email or password are null
if (!email || !password) {
reject('Invalid E-mail address or Password.');
}
// check if email is invalid
if (!EmailValidator.validate(email)) {
reject('Invalid E-mail address.');
}
// check if database already contains E-mail address
await User.findOne({email}).then((user: any) => {
if (user) {
reject('E-mail address already in use.'); // code should stop here
}
});
// anything below should not run
// create user object
const user = new User({
_id: new mongoose.Types.ObjectId(),
email: email,
password: password
});
// save user object to database
await user.save().then((result: any) => {
resolve(result);
}).catch((error: any) => {
reject(error);
});
});
};
auth.controller.ts
export const register = (req: Request, res: Response) => {
const email = req.body.email;
const password = req.body.password;
registerUser(email, password).then((user: User) => {
res.status(200).json(user);
}).catch((error: any) => {
res.status(300).json(error);
});
};
Upvotes: 0
Views: 57
Reputation: 350272
Returning new Promise()
inside an async
function is an antipattern: an async
function already returns a promise, so you only need to explicitly return the value that promise should resolve to.
The issue you describe is caused by the fact that you don't exit your function once you know its failure reason: the function will still continue the rest of the code if you don't also return
or throw
.
Tackling both issues, your code can be rewritten as follows:
const registerUser = async (email: string, password: string): Promise<User> => {
if (!email || !password) {
throw new Error('Invalid E-mail address or Password.');
}
if (!EmailValidator.validate(email)) {
throw new Error('Invalid E-mail address.');
}
let user: any = await User.findOne({email})
if (user) {
throw new Error('E-mail address already in use.');
}
user = new User({
_id: new mongoose.Types.ObjectId(),
email: email,
password: password
});
return user.save();
};
Note that throw
inside an async
function will make the promise (that the async
function always returns) reject with the reason you provide.
Note also that in the case of success, the resolution value is here a promise (user.save()
), so that means the promise of the async
function will link its resolution to the resolution of that promise.
Upvotes: 2