Stuart Brown Stuart Brown - 5 months ago 48
Node.js Question

Nodejs request - Cannot read property 'forEach' of undefined

I'm following a headless Drupal tutorial at http://blog.openlucius.com/en/blog/headless-drupal-nodejs-part-33-express-js-and-drupal-api-integration but my experience is with the Drupal side rather than the Node side so now that something is broken I'm not sure how to fix.

When starting the app I get an error:

/Library/WebServer/Documents/uno-fe/hellotest.js:23
blogsdata_all.blogs.forEach(function(item){
^

TypeError: Cannot read property 'forEach' of undefined
at Request._callback (/Library/WebServer/Documents/uno-fe/hellotest.js:23:24)
at Request.self.callback (/Library/WebServer/Documents/uno-fe/node_modules/request/request.js:200:22)
at emitTwo (events.js:87:13)
at Request.emit (events.js:172:7)
at Request.<anonymous> (/Library/WebServer/Documents/uno-fe/node_modules/request/request.js:1067:10)
at emitOne (events.js:82:20)
at Request.emit (events.js:169:7)
at IncomingMessage.<anonymous> (/Library/WebServer/Documents/uno-fe/node_modules/request/request.js:988:12)
at emitNone (events.js:72:20)
at IncomingMessage.emit (events.js:166:7)


my hellotest.js looks like:

var express = require('express');
var app = express();
var routes = require('./routes/index');
var request = require('request');
var blogsurlall = "http://www.pickingorganic.org/blogsexportall";

app.set('view engine','ejs');

var server = app.listen (2000, function(){
console.log('Waiting for you on port 2000');
});

request({
url:blogsurlall,
json:true
}, function(error, response, body){
if (!error && response.statusCode===200) {
blogsdata_all = body;
}

var blogs = [];

blogsdata_all.blogs.forEach(function(item){
blogs = blogs.concat(item);
});

app.locals.blogsdata = blogs;
})

app.use('/', routes);


I'm assuming this is something to do with the node request not fetching the json from the 'source' site correctly which is why blogs var is empty. Not sure what is going wrong tho - any help much appreciated!

Answer

You should console.log the response body to see how it looks like. Is it empty ?

As far as I see, the url is correct and the response is :

[{"title":"second post","created":"2016-06-30T15:49:17+08:00","field_blog_image":"  \n\n","path":"\/node\/2","created_1":"30 2016 Jun","body_1":"some content","body":"some content","uid":"","user_picture":""},{"title":"first post","created":"2016-06-28T21:56:52+08:00","field_blog_image":"  \n\n","path":"\/node\/1","created_1":"28 2016 Jun","body_1":"woot","body":"woot","uid":"","user_picture":""}]

If so, you should do your forEach this way :

blogsdata_all.forEach(function(item){
    blogs.push(item);
});

because the response body is an Array of objects. The way you are trying to loop through it would be correct if the response would be like this :

{"blogs":[{"title":"second post","created":"2016-06-30T15:49:17+08:00","field_blog_image":"  \n\n","path":"\/node\/2","created_1":"30 2016 Jun","body_1":"some content","body":"some content","uid":"","user_picture":""},{"title":"first post","created":"2016-06-28T21:56:52+08:00","field_blog_image":"  \n\n","path":"\/node\/1","created_1":"28 2016 Jun","body_1":"woot","body":"woot","uid":"","user_picture":""}] }

Also, you don't have to loop through it to push back the blog posts into a new Array, you can directly use :

app.locals.blogsdata = blogsdata_all;