Welcome to the Treehouse Community
Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.
Looking to learn something new?
Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.
Start your free trialMoira Lawrie-Martyn
8,073 PointsNodeJS request for JSON returns undefined every time
Hi guys,
So I'm trying to get some JSON data from another url to feed into the site that I've written. I know the JSON data is there as I've pulled it via curl on the command line.
But every single time I try to run it through the website, the script crashes with an undefined error.
Here's the code that's failing:
var request = require("request");
var parse = require('xml2js');
function getFile(year){
var data;
if(year < 2010)
{
var filename = year + ".xml";
}
else
{
var filename = year + ".json";
}
var url = <url> + filename;
request(url, function(error, response){
if(error){
data = fs.readFileSync("./data/" + filename, "utf8");
}
else
{
data = response;
console.log("call successful");
}
});
if(year < 2010)
{
data = parse.toJson(data); // for the few that are xml files
}
return data;
}
I've done everything I can think of to try and get it working. I really don't know what to do next. Can anyone help?
1 Answer
Michael Hulet
47,913 PointsIs your script crashing, or is it just return
ing undefined
every time? If it's crashing, that's a different issue, and an error log would be helpful, but it looks to me like it's probably just return
ing undefined
. This is because request
is an asynchronous function, which means that when you call it, your script won't wait for it to finish, and it'll keep on running all the code starting with if(year < 2010)
immediately, before the data you request
is downloaded. It'll get to return data
before the request finishes, and at that point, data
will still be undefined
, so your function will always return undefined
Ultimately, since request
is asynchronous and your function won't wait for it, there's no good way to make this function return
meaningful data. What you'll likely need to do is make your function accept a callback function as a second argument, and instead of return
ing data from getFiles
, pass the data you generate as an argument to the callback
function that you pass it
Moira Lawrie-Martyn
8,073 PointsMoira Lawrie-Martyn
8,073 PointsHi Michael, it looks like this is definitely the issue. I'm not used to dealing with async so it's throwing the rest of my code out. I've just got to work out how to build a callback in. Back to the drawing board >.<
Michael Hulet
47,913 PointsMichael Hulet
47,913 PointsDon't go back to the drawing board! Your code actually looks super solid rn. Asynchronous code is super hard for everyone, especially when you're first starting out, but I even everyone where I work has to stop and think about it for a second when they're dealing with it. Making a callback looks something like this:
Later on, calling that function looks something like this:
You can think of that callback function sort of like an asynchronous
return
mechanism, but one that just works when it's ready. You're already using that pattern when you callrequest
, you just have to make your function do something similarNewer versions of Node, however, support a syntax called
async
/await
, which is built on top of another abstraction calledPromise
s. There's a different version of the request library that uses them instead of callbacks. Basically, it allows you to write code that runs asynchronously, but looks like it's running like a normal synchronous function, like this:The
async
keyword tells JavaScript that it can pause your function until some of the calls it makes finishes, and theawait
keyword tells JavaScript to wait for a particular function call to finish before moving on with the rest of your function. Basically, it's all the benefits of asynchronous code without all of the mental difficulty of thinking about it. Later on in anotherasync
function, you can call your function like this: