0

Im working on a NodeJs app that takes an event from FB and puts it into a local database. For every event in the first page of the api query this goes well, except for the last one.

I am getting the following error:

[December 1st 2016, 1:48:39 pm] TypeError: Cannot read property 'name' of undefined at IncomingMessage. (/home/node/virgo/app.js:217:32) at IncomingMessage.emit (events.js:129:20) at _stream_readable.js:907:16 at process._tickCallback (node.js:372:11)

Just after

console.log(resultBody);

Code:

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

See graph api explorer for the breaking event: Graph API

Event code: 1682486658666506

I've tried catching the undefined json object with no luck, i've also tried to validate the json using this solution: Stackoverflow validate JSON javascript

Community
  • 1
  • 1

1 Answers1

1

Instead of https.request try using request.

It will give you parsed JSON and you won't have to do it manually.

If you want to do it manually like you do, then remember to wrap var json = JSON.parse(resultBody); in a try/catch block (or use tryjson) because the JSON.parse cannot be used on unknown data outside of a try/catch - it can throw exceptions.

Another thing, don't open you database connection in your route handlers. You should open the connection once and just use it in your handlers. See this answer for more info about it.

Right now you are connecting to the database but you continue outside of the connection callback, so you run all the lines beginning from var json = JSON.parse(resultBody); before the DB connection is established.

Additionally, the error may be not because json is undefined but because json.place is undefined.

You can change this:

var eventPlace = json.place.name;

to this:

var eventPlace = json.place && json.place.name;

You must also check json.photos before you access json.photos.data and test if json.photos.data is an array before you treat it as such (you can do it with:

if (json.photos && Array.isArray(json.photos.data)) {
  // ...
}

Basically, you need to make sure the values are what you want them to be before you access them. For example accessing this:

json.photos.data[json.photos.data.length-1].images[0].source

can fail when json is undefined, when json.photos is undefined, when json.photos.data is undefined, when json.photos.data is not an array, when json.photos.data.length is zero, when json.photos.data[json.photos.data.length-1] is undefined, when json.photos.data[json.photos.data.length-1].images is undefined, when json.photos.data[json.photos.data.length-1].images is not an array, when json.photos.data[json.photos.data.length-1].images is an array but it's empty, or when json.photos.data[json.photos.data.length-1].images is a non-empty array but json.photos.data[json.photos.data.length-1].images[0].source is undefined.

As you can see there are a lot of assumptions that you are doing here. When those assumptions are not met, the code will fail.

Community
  • 1
  • 1
rsp
  • 107,747
  • 29
  • 201
  • 177
  • A lot of usefull information thank you, luckily i can work with some assumption on the data since we are the ones making the events on facebook. The place not being available was an anomaly and is not going to happen in future events. However, it might indeed be a smart thing to get some checks in place for human errors. – Milan van Dijck Dec 02 '16 at 10:10