0

I have a very common scenario where I need to check if the user already exists in database? if yes, then return back an error to the user saying username already exists. I am using mongoose and its findOne method:

exports.registerUser = async (req, res) => {

    await userModel.findOne({'email': req.body.email}).exec().then((result) => {
        //user is already present in the db
        respondWithError(HttpStatus.BAD_REQUEST, "The user exists in the db")
    }).catch(error => {
        // user is not in the db - save
        saveTheUserToDb(req)
        res.render('home');
    })
}

here is my respondWithError function:

const respondWithError = (httpStatus, message) => {
    throw new BaseError(httpStatus, message)
}

and here is the BaseError

class BaseError extends Error {
    constructor(httpStatus, message) {
        super();
        this.httpStatus = httpStatus
        this.message = message
    }
}

The issue is that when findOne(...).exex() comes back and promise is resolved respondWithError is called which leads the execution directly into catch block where the user is saved in the DB which obviously is not what is intended.

What is the right way of sending back an error when it has to be in the resolve of a promise?

Toseef Zafar
  • 1,601
  • 4
  • 28
  • 46
  • 1
    Use `.then(throwError, saveNewUser)` instead of `.then(…).catch(…)`. However, in the onerror callback make sure to check that the `error` is actually a "not found" one, not some other kind of error. – Bergi Sep 16 '20 at 21:32
  • 1
    That's how promises work... if you `throw` inside a `.then()` callback, it will be caught by any `.catch()` following it. Since you are in an async function, you might be able to do something like: `exports.registerUser = async (req, res) => { const foundUser = await userModel.findOne({'email': req.body.email}).exec(); if (foundUser) { return respondWithError(HttpStatus.BAD_REQUEST, "The user exists in the db"); } saveTheUserToDb(req) res.render('home'); }` – andersryanc Sep 16 '20 at 21:33
  • @andersryanc I get this ```UnhandledPromiseRejectionWarning: Error: The user exists in the db``` in logs, and I dont get the reponse, the request never gets a response – Toseef Zafar Sep 16 '20 at 21:44
  • May be I wrong. But I'm think - your respondWithError function call BaseError (with super() call to parent class Error), whats why .catch {} block is applyed, and you got you db error message. I'm think it's not a good idea to save user in catch block anyway... Just use node debug tool (or simply console.log) to view thru call stack. – northernwind Sep 16 '20 at 21:52
  • It sounds like it's making it to my suggested `if (foundUser)` block and it's calling your `respondWithError()` function? ... I guess the larger question is how you are handling those `BaseErrors`? You must have a "middleware" / "error handler" at the end of your express setup which finally catches those and does something like `res.status(this.httpStatus).send(this.message)`? Normally I would just call `res.status(500).send("error message")` right in the handler, or have a helper func at least that receives `req, res` along with your args and calls that for you, instead of throwing an error. – andersryanc Sep 17 '20 at 22:18
  • @andersryanc yes I have a express middleware setup that catches the error, the issues is not catching it, the issue when I throw the error in ```resolve``` it leads to ```catch``` block which is how its supposed to work, so I replaced ```.then``` with a ```try catch```. os if user exists I ```respondeWithError``` in ```try``` block and which leads to ```catch``` and in ```catch``` I just do ```next(err)``` and that seems to have fixed the issue. – Toseef Zafar Sep 18 '20 at 08:30

0 Answers0