无法读取未定义的属性“标题”。 performance

您好我正在开发nodejs表示应用程序。 我收到exception,不知道为什么。 一切似乎都为我完美。 我的例外如下所示:

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) 

这里是app.post代码:

 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 }); }); 

而我的观点:

 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 -}) 

我也检查了我的MongoDB。 有数据。 我不知道为什么“标题”属性是“未定义”不知道。

这是一个竞赛条件问题。 从MongoDB中提取的两个函数是asynchronous的,所以调用res.render()发生在DB返回每个函数各自callback函数中的数据之前。 您需要嵌套每个function,以便他们有权访问正确的上下文。 见下文:

 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 }); }); }); }); 

但是,你可以看到,随着你越来越窝藏,这会变得非常混乱。 为了防止这种情况,你可以使用像caolan / async这样的控制stream库

边注:

你是Jade正在迭代一个comments数组,并且你从MongoDB返回一个单独的文档(假设你正在使用mongoose模块)。 您将需要将您的Mongoose函数从findOne()更改为find()以便mongoose可以返回具有正确postid的文档数组。

编辑:


Vinayak Mishra在指出可以使用Express路由中间件作为在路由中强制实施控制stream的方法时也是正确的。 这里是一个例子:

 // 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 ... }); } ); 

从db获取数据的两个例程是asynchronous例程,因此,在您触发res.render()时,不会调用它们的callback。 您将需要等待查询返回结果,然后调用渲染。

您可以利用中间件在准备好呈现post之前依次获取post和评论。

这是一个例子;

 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'); } 

让我知道是否无法遵循上面的代码中的任何东西。