Unable to read the 'title' property from undefined. express

Hi, I am creating a nodejs express application. I get an exception and don’t know why. Everything seems to be perfect for me. My exception is shown below:

500 TypeError: C:\Nodejs\NodejsBlog\apps\blog/views/postdetail.jade:23<br/> 21| .col- md-12 <br/> 22| .posts <br/> > 23| h3= post.title <br/> 24| p=post.body <br/> 25| p tag: <br/> 26| i=post.tag <br/><br/>Cannot read property 'title' of undefined 21| .col-md-12 22| .posts > 23| h3= post.title 24| p=post.body 25| p tag: 26| i=post.tag Cannot read property 'title' of undefined at eval (eval at (C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:152:8), :221:59) at C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:153:35 at Object.exports.render (C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:197:10) at Object.exports.renderFile (C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:233:18) at View.exports.renderFile [as engine] (C:\Nodejs\NodejsBlog\node_modules\jade\lib\jade.js:218:21) at View.render (C:\Nodejs\NodejsBlog\node_modules\express\lib\view.js:76:8) at Function.app.render (C:\Nodejs\NodejsBlog\node_modules\express\lib\application.js:504:10) at ServerResponse.res.render (C:\Nodejs\NodejsBlog\node_modules\express\lib\response.js:798:7) at C:\Nodejs\NodejsBlog\apps\blog\routes.js:64:14 at callbacks (C:\Nodejs\NodejsBlog\node_modules\express\lib\router\index.js:164:37) 

And here is the app.post code:

 app.get('/Post/:id',function(req,res){ var postdata; var comments; Post.findOne({_id:req.params.id},function(err, docs){ if(docs) { postdata=docs; console.log('Gönderi bulundu'); console.log(docs); console.log(postdata); console.log(postdata.title); } else { console.log('Gönderi bulunamadı'); } }); Comment.findOne({postid:req.params.id},function(err, docs){ if(docs) { console.log('Yorum bulundu'); console.log(docs); } else { comments=docs; console.log('Yorum bulunamadı'); } }); return res.render(__dirname+"/views/postdetail",{ title: 'adfasdf', stylesheet: 'postdetail', post:postdata, comments:comments }); }); 

And my opinion:

 extends ../../../views/bloglayout block js script(type='text/javascript') $(function() { $("#commentform" ).submit(function( event ) { alert( "Handler for .submit() called." ); $.ajax({ url: '/Post/Comment/', type: "POST", data: $('#commentform').serialize(), success: function(response){ alert('Yorum Kaydedildi'); } }); event.preventDefault(); }); }); block content .row .col-md-12 .posts h3=post.title p=post.body p tag: i=post.tag p Anahtar Kelimeler: b=post.keywords .row .col-md-4 h5 Yorum Yap form#commentform(role='form',action='/Post/Comment', method='post') input(type='hidden',name='comment[postid]',value=postdata._id) .form-group input.form-control(type='email',name='comment[email]',placeholder='E-posta adresi') .form-group input.form-control(type='text',name='comment[website]', placeholder='Website') .form-group textarea.form- control(type='text',name='comment[content]', placeholder='Yorum') button.btn.btn- default(type='submit') Ekle -comments.forEach(function(comment) { .well p b=comment.content p=comment.email -}) 

Also I checked my mongodb. There is data. I don’t know why the title property is undefined, I don’t know.

+6
source share
2 answers

This is a race problem. The two functions that are extracted from MongoDB are asynchronous, so the call to res.render() occurs before the database returns data in each function of the corresponding callback. You need to enclose each function so that they have access to the appropriate context. See below:

 app.get('/Post/:id', function (req, res, next){ Post.findOne({_id:req.params.id},function(err, postData){ if (err) return next(err); Comment.findOne({postid:req.params.id},function(err, comments){ if (err) return next(err); return res.render(__dirname+"/views/postdetail",{ title: 'adfasdf', stylesheet: 'postdetail', post:postData, comments:comments }); }); }); }); 

However, you can see how this can become quite dirty when you nest further and further. To prevent this, you can use a control flow library like caolan / async

Side note:

You Jade is looking for an iteration over the comments array, and you are returning a single document from MongoDB (assuming you are using the mongoose module). You will want to change your Mongoose function from findOne() to just find() so that mongoose can return an array of documents with the correct postid .

Edit:


Vinayak Mishra is also right in pointing out that you can use Express' middleware to impose a control flow on the route. Here is an example:

 // Use the app.param() method to pull the correct post doc from the database. // This is useful when you have other endpoints that will require work on // a Post document like PUT /post/:postid app.param('postid', function (req, res, next, id) { Post.findById(id, function (err, post) { if (err) return next(err); if (!post) return next('route'); req.post = post; }); }); app.get('/post/:postid', // -- First route middleware grabs comments from post doc saved to req.post function (req, res, next) { Comment.find({ postid: req.post.id }, function (err, comments) { if (err) return next(err); req.comments = comments; next(); }); }, // -- This route middleware renders the view function (req, res, next) { res.render('/postDetail', { // ... list locals here ... }); } ); 
+3
source

Two routines for extracting data from db are asynchronous routines, so their callbacks are not called at the time res.render() run. You will need to wait until the queries return the results, and then call the render.

You can use middlewares to select messages and comments sequentially before you are ready to post.

Here is an illustration:

 app.get('/Post/:id', fetchPost, fetchComments, renderPost, handleErrors); function fetchPost(req, res, next) { Post.findOne({ _id: req.params.id }, function (err, docs) { if (!err && docs) { console.log('Gönderi bulundu'); req.postdata = docs; next(); } else { console.log('Gönderi bulunamadı'); next(err || new Error('No such post: ' + req.params.id)); } }); } function fetchComments(req, res, next) { Comment.findOne({ postid: req.params.id }, function (err, comments) { if (!err) { console.log('Yorum bulundu'); req.postComments = comments || []; next(); } else { console.log('Yorum bulunamadı'); next(err); } }); } function renderPost(req, res, next) { res.locals.post = req.postdata; res.locals.comments = req.postComments; res.locals.title = 'adfasdf - anything that fits'; res.locals.stylesheet = 'postdetail'; return res.render(__dirname + '/views/postdetail'); } function handleErrors(err, req, res, next) { // You'll get here only if you recieved an error in any of the previous middlewares console.log(err); // handle error and show nice message or a 404 page res.locals.errmsg = err.message; res.render(__dirname + '/views/error'); } 

Let me know if you cannot follow anything in the code above.

0
source

Source: https://habr.com/ru/post/959426/


All Articles