Kymz
Kymz

Reputation: 71

Unhandled promise rejection Error: Can't set headers after they are sent

I would like to make a if else return (for conrtole) but: "UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: Can't set headers after they are sent. "

exports.delete = function (req, res) {
  Parking.findById(req.params.id).exec()
    .then(function (parking) {
      if (userController.ensureAuthorized(req, 'Director', parking.id)) {
        return parking;
      }
      return res.status(403).send({msg: 'unauthorized'});

    })
    .then(function (parking) {
      User.update().exec();
      return parking;
    })
    .then(function (parking) {
       return Parking.remove({_id: parking._id}).exec();
    })
    .then(function () {
      res.status(200).json({msg: 'Ok ! Parkink remove'});
    })
    .catch(function (err) {
      return res.status(400).send(err);
    });
};

Ty

Upvotes: 0

Views: 3785

Answers (3)

lecstor
lecstor

Reputation: 5707

just as an addition to the other answers given, I would recommend:

1) breaking things up into small parts

2) using throw as intended, to raise the error of non-authorization

function update (parking) {
  User.update().exec()
    .then(function () {
      Parking.remove({_id: parking._id}).exec();
    });
}

exports.delete = function (req, res) {
  // auth needs req so we put it in scope
  var auth = function (parking) {
    if (!userController.ensureAuthorized(req, 'Director', parking.id)) {
      throw(new Error(403));
    }
    return parking;
  }

  Parking.findById(req.params.id).exec()
    .then(auth)
    .then(update)
    .then(function () {
      res.status(200).json({msg: 'Ok ! Parkink remove'});
    })
    .catch(function (err) {
      if (err.message === 403) {
        return res.status(403).send({msg: 'unauthorized'});
      }
      return res.status(400).send(err);
    });
};

Upvotes: 0

robertklep
robertklep

Reputation: 203304

The issue is that after return res.status(403), the promise chain doesn't stop automagically. Eventually, it will hit res.status(200) and cause the error.

You can rewrite your promise chain a bit to prevent this. I'm not sure what the purpose of that User.update().exec() is, but I assume that you wanted to call it and also wait for its promise to get resolved before continuing:

exports.delete = function (req, res) {
  Parking.findById(req.params.id).exec()
    .then(function (parking) {
      if (userController.ensureAuthorized(req, 'Director', parking.id)) {
        return User.update(...).exec().then(function() {
          return Parking.remove({_id: parking._id}).exec();
        }).then(function() {
          return res.status(200).json({msg: 'Ok ! Parkink remove'});
        });
      } else {
        return res.status(403).send({msg: 'unauthorized'});
      }
    }).catch(function (err) {
      return res.status(400).send(err);
    });
};

Upvotes: 1

Shaharyar
Shaharyar

Reputation: 12439

Well there is no standard way of breaking the promise chain.

So I am going to throw an error to break the chain, and then handle that custom thrown error:

exports.delete = function (req, res) {
  Parking.findById(req.params.id).exec()
    .then(function (parking) {
      if (userController.ensureAuthorized(req, 'Director', parking.id)) {
        return parking;
      }
      else {
        res.status(403).send({msg: 'unauthorized'});
        throw new Error('BREAK_CHAIN'); //      <-- intentionally throw error
      }
    })
    .then(function (parking) {
      User.update().exec();
      return parking;
    })
    .then(function (parking) {
       return Parking.remove({_id: parking._id}).exec();
    })
    .then(function () {
      res.status(200).json({msg: 'Ok ! Parkink remove'});
    })
    .catch(function (err) {
        if(err.message != 'BREAK_CHAIN')    //      <-- handle if error was intentionally thrown
            return res.status(400).send(err);
    });
};

Upvotes: 0

Related Questions