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 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" href="/manage/edit/<%= data[i].id %>"><%=__('Edit')%></a></span>
<span><a class="btn btn-danger" href="/manage/delete/<%= data[i].id %>"><%=__('Delete')%></a></span>
</span>
</div>
</div>
</div>
<% }
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 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" href="/manage/edit/<%= data[i].id %>"><%=__('Edit')%></a></span>
<span><a class="btn btn-danger" href="/manage/delete/<%= data[i].id %>"><%=__('Delete')%></a></span>
</span>
</div>
</div>
</div>
<% }
Share
Improve this question
asked Jan 17, 2016 at 1:36
KwaadjeiKwaadjei
3092 gold badges5 silver badges18 bronze badges
5
-
Why not wrap your function in a
try/catch
? – mwilson Commented Jan 17, 2016 at 1:39 -
You realize you have syntax errors, and the line with
GuestUserID
has two closing%>
– adeneo Commented Jan 17, 2016 at 1:42 -
The error says "cannot read property _id of null", meaning either
UserID
orGuestUserID
isnull
, notundefined
– adeneo Commented Jan 17, 2016 at 2:20 - @adeneo , you are right, and in an event like that, i want to display an appropraite message to the user instead of what i currently get – Kwaadjei Commented Jan 17, 2016 at 2:25
-
Then you check for
null
, and display whatever message you want, wrapping every route in try/catch blocks seems like a horrible way to solve it imo. – adeneo Commented Jan 17, 2016 at 2:28
1 Answer
Reset to default 4To 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 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);
// ...