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 trial

JavaScript

Node.js Basics Course

I had a question relating to the node.js basics course:

I was trying to complete the extra credit step and create a way to retrieve data from the "forecast.io" site, however, I cannot figure out how to execute the following code:

var request = http.get("http://teamtreehouse.com/" + username + ".json", function(response) {
  var body = "";
  //Read the data
  response.on("data", function (chunk){
  body += chunk;
  });

The specific part that I am wondering about is the username variable. When you go to the forecast.io website, it does not have a specific url that just differs by a obvious (to me) difference (in the treehouse case it was the username i.e. 'chalkers' for Andrew Chalkley etc.). If anyone has any suggestions or has completed this, please share your coments/solution. Thanks

I have not completed the extra credit but I think that maybe the forecast has json data embed into object so you cannot just call username out. The only way to be sure what you are calling is to check the websites api or json reference. Json has {key: value}; the key may something different than username since someone else built the format not treehouse.

Hi Aaron HARPT, I've formatted your code with the three backticks (```). It looks like you accidentally used single quotes instead.

3 Answers

Hi Aaron HARPT, first up, it looks like your code is missing a set of closing curly braces and parentheses, for the http.get function. The one at the bottom of the code you pasted in would close the response.on function only.

Second, the body variable would contain the data chunks concatenated together, but it doesn't look like it's being displayed to the user in any way. I think in the course Andrew used a simple console.log() to output it to the console.

Third, the Forecast.io API requires an API key, a latitude and longitude, and optionally, a time.

You should first register an account to use the API (don't worry, it's free for basic usage).

The easiest way to get the latitude and longitude values is to go to the Forecast.io homepage and enter a location in the search, then grab the lat/longs from the last part of the result URL. For example, New York, NY: forecast.io/#/f/40.7142,-74.0064

Then you should be able to use the following URL format in your API call:

https://api.forecast.io/forecast/APIKEY/LATITUDE,LONGITUDE

Which for New York, NY would look a bit like this (not a real API key):

https://api.forecast.io/forecast/H4tAdrR9DWkZ3vTjVMu5ciyC8XpYaESe/40.7142,-74.0064

Here is my code, with a bit of an added bonus of using the Google Geocoding API so you can input an address or city instead of lat/longs to get the weather: http://w.trhou.se/06burhw8hy

Note that to use my code, you'll need to fork the workspace and then get your own API keys.

I've just thrown my app on Github too if you or anyone prefers to use that: https://github.com/iainsimmons/nodejs-weather

I found your code incredibly helpful while figuring out a solution to the extra credit. Thank you for taking the time to share it!

Mr. Simmons- Thank you for your help; Here is my code, and I would greatly appreciate if you would take the time to review and explain what I am doing wrong. I appreciate your willingness to help me with this.

Aaron

Here is my forecast-app.js:

var profile = require("./forecast-profile.js");
var users = process.argv.slice(2);
users.forEach(profile.get);

My forecast-profile.js:

var https = require("https");


var location = "66221";

function printMessage(location, temperature,) {
var message = location + " is " + temperature + " degrees.";
  console.log(message);
}




function printError(error) {
 console.error(error.message);
}


function get(location){
  //Connect to the API URL (https://api.forecast.io/forecast/APIKEY/LATITUDE,LONGITUDE)
  var request = http.get("https://api.forecast.io/forecast/" + APIKEY + "/" + Latitude + "," + Longitude, function(response) {
  var body = "";
  //Read the data
  response.on("data", function (chunk){
  body += chunk;
  });
  response.on("end", function() {
    if(response.statusCode === 200) {
    try {
       //Parse the data
      var forecast = JSON.parse(body);
      //Print the data
      printMessage(location, forecast.temperature, forecast.degrees);
    } catch(error) {
      //Parse Error
      printError(error);
  } 
    } else {
        //Status Code Error
      printError({message: "There was an error getting the profile for " + username + ". (" +     
             http.STATUS_CODES[response.statusCode] + ")" });
    }
  });



  });
  //Connection Error
  request.on("error", printError);
}

module.exports.get = get;

Okay, so first, in your forecast-app.js, you're still using variables that relate to user profiles instead of weather for locations. You don't have to change them, but it will make more sense looking at your code in future if you title your variables to describe what they represent in your project.

Second, the process.argv.slice(2) means get the third argument from the command used to run the script/app, and every argument after that, as an array. When you run a Node app like the example, node is the first, the filename of your script is the second, and then you're getting all the arguments after that:

node forecast-app.js location1 location2 location3

Third, you're then running the get function from your other script on each one of those arguments, passing it as the location parameter. I'm not sure why, but you also have a local location variable in the forecast-profile.js script. If that's just for testing, that's fine, but otherwise you shouldn't need it.

Fourth, your request is expecting the variables APIKEY, Latitude and Longitude, none of which are defined here. You should define variables or parameters in camelCase in JavaScript. And ideally, you'd be passing the latitude and longitude as parameters to the function, not a single location(unless you also do something to get the lat/longs from the one location variable). Your apiKey could be defined either just within this script, or in another script and then imported as a module. Just don't share it with anyone (even here), because they could abuse it and potentially get you in trouble.

Fifth, in the line where you print the data from the response, you're passing 3 parameters to the function printMessage, when it has been defined as only accepting 2 (location & temperature). I assume temperature and degrees would be the same thing, and I believe the current temperature in the response from Forecast.io is accessed using currently.temperature, or in your case, forecast.currently.temperature.

Sixth, I just noticed that you're importing https, then using http.get and http.STATUS_CODES in your code. Since you're sending a secure/HTTPS GET request to Forecast.io, you'll need to use https.get. To use http.STATUS_CODES, you'll also need to import the http module, so add the following to the top:

var http = require("http");

And lastly, your status code error message is still describing the error as if it were a user profile app, not a weather app.