我正在开发一个NodeJs应用程序,该应用程序从FB获取事件并将其放入本地数据库。对于api查询的第一页中的每个事件,这都很顺利,除了最后一个。
我收到以下错误:
[2016年12月1日,下午1:48:39] TypeError:无法读取属性'name' 未定义的 在IncomingMessage。 (/home/node/virgo/app.js:217:32) 在IncomingMessage.emit(events.js:129:20) 在_stream_readable.js:907:16 at process._tickCallback(node.js:372:11)
在
之后console.log(resultBody);
代码:
function addFBEvent(facebookId){
console.log("getting event: " + facebookId);
var options = {
hostname: 'graph.facebook.com',
port: 443,
path: '/v2.8/'+facebookId+'?fields=name,description,start_time,end_time,place,photos{images}&access_token={INSERT API ACCESS CODE HERE}',
method: 'GET'
};
https.request(options, function(res2) {
var resultBody = "";
res2.setEncoding('utf8');
res2.on('data', function (chunk) {
resultBody = resultBody + chunk;
});
res2.on('end', function () {
dbConnection = sql.createConnection({
host : settings.dbHost,
user : settings.dbUser,
password : settings.dbPassword
});
dbConnection.connect(function(err){
if(!err) {
console.log("Database is connected ... nn");
} else {
console.log("Error connecting database ... nn");
}
});
var json = JSON.parse(resultBody);
console.log(resultBody);
if (json != undefined){
var eventName = json.name;
var eventStart = json.start_time;
var eventEnd = json.end_time;
var eventDescription = json.description;
var eventPlace = json.place.name;
var eventPoster = json.photos.data[json.photos.data.length-1].images[0].source;
var eventId = json.id;
console.log("name: " + eventName + ", start: " + eventStart + ", end: " + eventEnd + ", place: " + eventPlace + ", Poster: " + eventPoster);
//console.log("Description: " + eventDescription);
dbConnection.query('INSERT INTO SVVirgo.activities(title, description, image, start, end, price, location, facebook) VALUES ("'+eventName+'","'+eventDescription+'","'+eventPoster+'","'+eventStart+'","'+eventEnd+'",0,"'+eventPlace+'","'+eventId+'")', function (err, result){
});
}
dbConnection.end();
})
}).end();
}
请参阅图表api资源管理器了解中断事件:Graph API
活动代码:1682486658666506
我试过没有运气捕获未定义的json对象,我也尝试使用此解决方案验证json:Stackoverflow validate JSON javascript
答案 0 :(得分:1)
而不是https.request
尝试使用request
。
它将为您提供已解析的JSON,您不必手动执行此操作。
如果你想像你一样手动完成,那么记得将var json = JSON.parse(resultBody);
包装在try / catch块中(或使用tryjson
),因为JSON.parse
不能用于未知try / catch之外的数据 - 它可以抛出异常。
另一件事是,不要在路由处理程序中打开数据库连接。您应该打开一次连接,然后在处理程序中使用它。有关详情,请参阅this answer。
现在您正在连接到数据库,但是您继续在连接回调之外,因此在建立数据库连接之前运行从var json = JSON.parse(resultBody);
开始的所有行。
此外,错误可能不是因为json
未定义,而是因为json.place
未定义。
你可以改变这个:
var eventPlace = json.place.name;
到此:
var eventPlace = json.place && json.place.name;
在访问json.photos
之前,您还必须先检查json.photos.data
,然后在对待json.photos.data
之前测试if (json.photos && Array.isArray(json.photos.data)) {
// ...
}
是否为数组(您可以执行以下操作:
json.photos.data[json.photos.data.length-1].images[0].source
基本上,在访问它们之前,您需要确保这些值是您希望它们的值。例如访问:
json
未定义json.photos
,未定义json.photos.data
,未定义json.photos.data
,json.photos.data.length
不是数组时,json.photos.data[json.photos.data.length-1]
为json.photos.data[json.photos.data.length-1].images
时,会失败零,未定义json.photos.data[json.photos.data.length-1].images
时,json.photos.data[json.photos.data.length-1].images
未定义时,json.photos.data[json.photos.data.length-1].images
不是数组时,json.photos.data[json.photos.data.length-1].images[0].source
是数组但是它是空的,或者何时{{1}}是非空数组,但{{1}}未定义。
正如您所看到的,您在这里做了很多假设。如果不满足这些假设,代码将失败。