Domanda

I am trying to understand Q Promises and how to handle two different errors thrown from two different then blocks.

Here is the function I would like to "Promisfy":

router.post('/user', function(req, res) {
  var user = new User(req.body);
  User.findOne({ email: req.body.email }, function(error, foundUser) {
    if(foundUser) {
      res.send("Error: User with email " + foundUser.email + " already exists.", 409);
    } else {
      User.create(user, function(err, createdUser) {
        if (err) {
          res.send(err, 400);
        } else {
          res.json({ id: createdUser.id }, 201);
        }
      });
    }
  });  
});

It takes some User details, and tries to create a new User if one doesn't exist already with the same email. If one does, send a 409. I also handle the normal mongoose error with a 400.

I've tried using mongoose-q to convert it over, and I end up with this:

router.post('/user', function(req, res) {
  var user = new User(req.body);
  User.findOneQ({email : req.body.email})
  .then(function(existingUser) {
    if (existingUser) {
      res.send("Error: User with email " + existingUser.email + " already exists.", 409);
    } 
    return User.create(user);
  })
  .then(function(createdUser) { 
    res.json({ id: createdUser.id }, 201); 
  })
  .fail(function(err) { 
    res.send(err, 400)
  })
});

Is this correct? Is there anyway to push that existing user check into a fail block? I.e. throw an Error, and then catch it and deal with it?

Something like this perhaps:

router.post('/user', function(req, res) {
  var user = new User(req.body);
  User.findOneQ({email : req.body.email})
  .then(function(existingUser) {
    if (existingUser) {
      throw new Error("Error: User with email " + existingUser.email + " already exists.");
    } 
    return User.create(user);
  })
  .then(function(createdUser) { 
    res.json({ id: createdUser.id }, 201); 
  })
  .fail(function(duplicateEmailError) {
    res.send(duplicateEmailError.message)
  })
  .fail(function(mongoError) { 
    res.send(mongoError, 400)
  })
});
È stato utile?

Soluzione

I'm not experienced enough with Q. However, I can answer with bluebird.

bluebird supports typed catches. Which means you can create new Error subclasses, throw them, and handle them accordingly.

I've used newerror in my example to simplify the creation of Error subclasses.

var newerror = require('newerror');

var DuplicateEmailError = newerror('DuplicateEmailError');

router.post('/user', function(req, res) {
    var user = new User(req.body);
    User.findOneAsync({ email: req.body.email }).then(function(existingUser) {
        if (existingUser) {
            throw new DuplicateEmailError('Error: User with email ' + existingUser.email + ' already exists.');
        }

        return User.createAsync(user);
    }).then(function(createdUser) {
        res.json({ id: createdUser.id }, 201);
    }).catch(DuplicateEmailError, function(err) {
        res.send(err.message, 409);
    }).catch(function(err) {
        res.send(err.message, 500);
    });
});
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top