Ad

How To Catch Errors When Rendering Ejs View Node.js

- 1 answer

Please I have notice that anything i return records from a database which contains some missing data my view renders with an error page like show in the image, everything about my code looks correct, but if there is for example a missing ID in the data records for any reason. I get undefined. Which should be expected. But my problem is how to I avoid this and catch such errors or possibly render a decent view with a message. I have this as my server code

ItemOffers.paginate({'OfferedByID': req.user._id}, {
    page: page,
    limit: 10,
    populate: ['UserID', 'GuestUserID']
}, function (err, result, pageCount) {
    if (err) {
        console.log('Error Occured' + err)
    }
    console.log(result);
    mypageCount = pageCount;
    res.render('manageoffers', {data: result, mylink: data, PCount: pageCount ,SuccessMessage: req.flash('SuccessMessage'), ErrorMessage: req.flash('ValidationError')});
});

and this in my ejs template

  <% if(data.length){
                        for(var i in data){ %>
                <div class="article-detail">
                    <div class="product-detail">
                        <img  alt="No image" src="/images/<%= data[i].ItemImage %>">
                        <div class="description"><h5 style="color: #0044cc"> <%= data[i].ItemName %></h5>
                            <span><b><%=__('Item Number:')%></b><%= data[i].ItemNumber.toUpperCase() %> </span>
                            <span ><b><%=__('Borrowed Date:')%></b></span>
                            <span class="head2"><%= data[i].BorrowDate.toDateString() %> </span><br>
                            <span><b><%=__('Offer Type:')%></b><%= data[i].OfferType%> </span>
                            <span><b><%=__('Booking Number:')%> </b><%= data[i].BookingNo.toUpperCase() %> </span><br>
                            <span class="head1"><b><%=__('Return Date:')%></b></span><span class="head2" style="color:crimson;"><%= data[i].ReturnDate.toDateString() %> </span>
                            <span><b><%=__('Offer Status:')%></b><%= data[i].ItemStatus %> </span><br>
                            <span class="spl-chr"><%=__('Offered to:')%><a target="_blank" rel="nofollow noreferrer" href="/user/<%= typeof data[i].UserID!='undefined' ? data[i].UserID._id:data[i].GuestUserID._id %> %>"><%= typeof data[i].UserID!='undefined' ? data[i].UserID.UserName:data[i].GuestUserID.FirstName %></a></span>
                            <span class="manage-btn">                                 
                                <span><a class="btn btn-default" target="_blank" rel="nofollow noreferrer" href="/manage/edit/<%= data[i].id %>"><%=__('Edit')%></a></span>
                                <span><a class="btn btn-danger" target="_blank" rel="nofollow noreferrer" href="/manage/delete/<%= data[i].id %>"><%=__('Delete')%></a></span>
                            </span>
                        </div>
                    </div>
                </div>
                <% }

enter image description here

Ad

Answer

To properly report errors in node, I use errorhandler

var errorHandler = require('errorhandler');

at the top and

if( env == 'development')
{
    errorHandler.title = "Ups...";
    app.use(errorHandler());
}

just before the app.listen(), but this is only to show a properly formatted error page useful during development.

If you want to catch the errors in production and display an alternative (user visible) view, then you should use express middleware architecture. You can define a custom error class and use it to pass info from the view that failed to the error handler function:

// define a custom error class
function MyCustomError(customInfo)
{
    Error.captureStackTrace(this, this.constructor);
    this.name = this.constructor.name;
    this.message = "error:" + customInfo;
}
util.inherits(MyCustomError, Error);

// your view
function view1(req,res,next)
{
   try {
     //... prepare context
     return res.render('template.ejs', context);
   }
   catch(e)
   {
     // here you can analyze the cause of error and pass useful info to
     // error handler
     return next(new MyCustomError('template failed:' + e.message));
   }
}

function handleError: function(err,req,res,next)
{
  // it's up to you how you handle the error, you can render an
  // alternate view or rreq,res,next)
{
   try {
     //... prepare context
     return res.render('template.ejs', context);
   }
   catch(e)
   {
     // here you can analyze the cause of error and pass useful info to
     // error handler
     return next(new MyCustomError('template failed:' + e.message));
   }
}

function handleError: function(err,req,res,next)
{
  // it's up to you how you handle the error, you can render an
  // alternate view or redirect to an error view
  if( err instanceof MyCustomError )
     return res.redirect(301, 'error.html');

   next(err);
}

// all of this is set up like this
// ...
app.get('/view1',view1);
app.use(handleError);
// ...
Ad
source: stackoverflow.com
Ad