Why are my JS promises breaking error objects empty?

Introduction:

  • Using Mongoose
  • Using Bluebird and replacing mpromise inside Mongoose
  • The req.helpers.consoleMessage function described below is a function with some simple logic in it that determines when and not to show a certain level of detail based on existing debugging included in the application configuration. And the non-empty / undefined state of the displayed objects. All messages get stringified using JSON and are returned for display on the console.

Code:

Here is an example of some code showing these symptoms.

This is the delete route for :team :comment units in the API I'm working on. I intentionally left the line var response = user.comments; with an error in it referring to the user object, when in fact it should be team , which should be returned by the calling function and passed to Promise .then() . This should cause a reference error because the user is not defined.

  var console = clim("(DELETE /api/v1/team/:team/comments/:comment):", logger); // create a filters request for mongoose var query = {}; // determine if the :team param is a username or an object id req.helpers.validateObjectId(req.db, req.params.team) ? query._id = req.params.team : query.name = req.params.team; if(req.helpers.validateObjectId(req.db, req.params.comment)) { // looks good; create an update object var update = { $pull: { comments: { _id: req.params.comment } } }; // find the comment using the query above and pull the comment id req.models.Team.findOneAndUpdate( query, update, {safe: true, new : true} ).then(function(team){ if(!team){ // create the response object var response = { success: false, message: "Team not found" }; // log request console.info(req.helpers.consoleMessage(req, response, null)); // respond with an appropriate array res.status(404).json(response); }else{ // create the response object using the teams comments var response = user.comments; // log request console.info(req.helpers.consoleMessage(req, response, null)); // respond with the team comments array res.status(200).json(response); } }).then(null, function(err){ // create the response var response = { success: false, message: req.config.debug ? err: "An error has occur with your request; please try again" }; // log the errors console.error(req.helpers.consoleMessage(req, response, err)); // or send a 500 internal server error res.status(500).json(response); }); }else{ // create the response var response = { success: false, message: "Comment id is not a valid object id" }; // log the errors console.info(req.helpers.consoleMessage(req, response, null)); // or send a 500 internal server error res.status(500).json(response); } 

Problem:

Calling this route will result in an error and trigger .catch() in an attempt to recover from an error state, however, the err object appears empty.

Ex. HTTP response: { success: false, message: {} }

Ex. Console log (shortened for clarity) { req: {...}, res: {...}. err: {} } { req: {...}, res: {...}. err: {} }

Output:

The err object seems empty ...

+5
source share
1 answer

Problem:

Writing an error object to the console in itself will show that the object is really not empty, and capture properties such as err.message are very doable.

The problem is that the JS Error object cannot be naively stiffened with JSON . This - along with ways to solve this problem - is described in detail in the related SOF question: Is it not possible to output an error using JSON.stringify? .

Updated code:

The following code changes were made to indicate the message in the HTTP response, and the helper function (previously described) was updated for the specific details of the displayed error: Ex: { err: { message: err.message, stack: err.stack } } and etc.

  var console = clim("(DELETE /api/v1/team/:team/comments/:comment):", logger); // create a filters request for mongoose var query = {}; // determine if the :team param is a username or an object id req.helpers.validateObjectId(req.db, req.params.team) ? query._id = req.params.team : query.name = req.params.team; if(req.helpers.validateObjectId(req.db, req.params.comment)) { // looks good; create an update object var update = { $pull: { comments: { _id: req.params.comment } } }; // find the comment using the query above and pull the comment id req.models.Team.findOneAndUpdate( query, update, {safe: true, new : true} ).then(function(team){ if(!team){ // create the response object var response = { success: false, message: "Team not found" }; // log request console.info(req.helpers.consoleMessage(req, response, null)); // respond with an appropriate array res.status(404).json(response); }else{ // create the response object using the teams comments var response = team.comments; // log request console.info(req.helpers.consoleMessage(req, response, null)); // respond with the team comments array res.status(200).json(response); } }).then(null, function(err){ // create the response var response = { success: false, message: req.config.debug ? err.message : "An error has occur with your request; please try again" }; // log the errors console.error(req.helpers.consoleMessage(req, response, err)); // or send a 500 internal server error res.status(500).json(response); }); }else{ // create the response var response = { success: false, message: "Comment id is not a valid object id" }; // log the errors console.info(req.helpers.consoleMessage(req, response, null)); // or send a 500 internal server error res.status(500).json(response); } 

Why am I using such a simple concept?

I searched the clock, trying to figure out what I was doing wrong with my promise chain structures, and used the keywords empty and error (along with each combination of words regarding JS Promises), but none of my searches came up with anything useful other than confirming that that I approached correctly. Everything turned out to be in order with my helper script, and I could not take the correct debugging steps to find out where the problem was, until it happened when I try to output the err object directly to the console (why should I do this? I already was. .. or so I thought).

So, I think you could say that I’m trying to save some people for a while in case someone encounters a similar situation and thinks: “Why does my promises not work as intended!” and, like me, the search is in the wrong direction.

Happy coding!

+8
source

All Articles