我正在开发nodejs express app。我越来越异常,不知道为什么。一切似乎都适合我。我的例外情况如下所示:
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。有数据。我不知道为什么'title'属性'未定义'不知道。
答案 0 :(得分:3)
这是竞争条件问题。从MongoDB中提取的两个函数是异步的,因此对res.render()
的调用发生在DB返回每个函数各自的回调中的数据之前。您需要嵌套每个函数,以便它们可以访问正确的上下文。见下文:
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
旁注:
你是Jade想要迭代一个
comments
数组,你从MongoDB返回一个文档(假设你正在使用mongoose
模块)。您需要将您的Mongoose功能从findOne()
更改为find()
,以便mongoose
可以使用正确的postid
返回一系列文档。
Vinayak Mishra也指出你可以使用Express'路由中间件作为在路由中施加控制流的方法。这是一个例子:
// 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 ...
});
}
);
答案 1 :(得分:0)
从db获取数据的两个例程是异步例程,因此在您触发res.render()
时不会调用它们的回调。您需要等待查询返回结果,然后调用render。
在准备好发布帖子之前,您可以利用中间件依次获取帖子和评论。
这是一个例子;
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');
}
如果我们无法遵循上述代码中的任何内容,请告诉我。