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
Steven Byington
13,584 PointsNode.js forecast extra credit
I tried out the extra credit for node.js, where we were asked to create a console app using the forecast.io api. I got it to work, but wanted any feedback I could get to help clean up the code.
here is my forecast.js file
var forecast = require("./zipcodes");
var zip = process.argv.slice(2);
zip.forEach(forecast.getZip);
and here is my zipcodes.js
var http = require("http");
var https = require('https');
//Print out message
function printMessage(city, temp, soonSummary) {
var message = "Current temp for " + city + " is " + temp + " degrees with "+ soonSummary;
console.log(message);
}
//Print out error
function printError(error) {
console.error(error.message);
}
function getZip(zip) {
//Get zip
var request = http.get("http://api.zippopotam.us/us/" + zip, function(res){
var body = "";
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function() {
if(res.statusCode === 200 ) {
try {
//Parse the data
var zipCodeInfo = JSON.parse(body);
//return the latitude and longitude
var latitude = zipCodeInfo.places[0].latitude;
var longitude = zipCodeInfo.places[0].longitude;
var city = zipCodeInfo.places[0]["place name"];
//Request info from forecast.io api
var request = https.get("https://api.forecast.io/forecast/(api key)/" + latitude + "," + longitude, function(res) {
var body = "";
//Read the data
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function() {
if(res.statusCode === 200 ) {
try {
//Parse the data
var weather = JSON.parse(body);
//Print the data
printMessage(city, weather.currently.temperature, weather.minutely["summary"]);
} catch (error){
//Parse error
console.error("There was an error parsing the forecast data - " + error);
}
} else {
//Status Code Error
printError({message: "There was an error getting the forecast for " + username + "(" + http.STATUS_CODES[res.statusCode] + ")"});
}
});
});
//Connection error
request.on('error', printError);
} catch (error){
//Parse error
console.error("There was an error parsing the Zip Code data - " + error);
}
} else {
//Status Code Error
printError({message: "There was an error getting the Zip Code for " + zip + "(" + http.STATUS_CODES[res.statusCode] + ")"});
}
});
});
//connection error
request.on('error', printError);
}
module.exports.getZip = getZip;
I have the api key in my personal file, but left it out here. You can insert yours where my parenthesis are, and it should work just fine.
4 Answers
Robert Richey
Courses Plus Student 16,352 PointsHi Steven,
This is really awesome, thanks for sharing. Because you asked for feedback, here is the program with changes I made. Basically, I broke the lower half of getZip into another function getForecast passing in a location object holding latitude, longitude and city.
var http = require("http");
var https = require("https");
// Print out message
function printMessage(city, temp, soonSummary) {
var message = "Current temp for " + city + " is " + temp + " degrees with " + soonSummary;
console.log(message);
}
// Print out error
function printError(error) {
console.error(error.message);
}
function getForecast(location) {
var url = "https://api.forecast.io/forecast/";
var key = //(Your API key)
url += key + "/" + location.latitude + "," + location.longitude;
//Request info from forecast.io api
var request = https.get(url, function(res) {
var body = "";
//Read the data
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function() {
if(res.statusCode === 200 ) {
try {
//Parse the data
var weather = JSON.parse(body);
//Print the data
printMessage(location.city, weather.currently.temperature, weather.minutely["summary"]);
} catch (error){
//Parse error
console.error("There was an error parsing the forecast data - " + error);
}
} else {
//Status Code Error
printError({message: "There was an error getting the forecast for " + username + " (" + http.STATUS_CODES[res.statusCode] + ")"});
}
});
//Connection error
request.on('error', printError);
});
}
function getZip(zip) {
//Get zip
var request = http.get("http://api.zippopotam.us/us/" + zip, function(res) {
var body = "";
res.on('data', function (chunk) {
body += chunk;
});
res.on('error', function() {
//Status Code Error
printError({message: "There was an error getting the Zip Code for " +
zip + " (" + http.STATUS_CODES[res.statusCode] + ")"});
});
res.on('end', function(res) {
try {
//Parse the data
var zipCodeInfo = JSON.parse(body);
//return the latitude and longitude
var location = {};
location.latitude = zipCodeInfo.places[0].latitude;
location.longitude = zipCodeInfo.places[0].longitude;
location.city = zipCodeInfo.places[0]["place name"];
} catch(error) {
//Parse error
console.error("There was an error parsing the Zip Code data - " + error);
return;
}
getForecast(location);
});
});
//connection error
request.on('error', printError);
}
module.exports.getZip = getZip;
Andrew Chalkley
Treehouse Guest TeacherAwesome!
I notice you still have username :)
printError({message: "There was an error getting the forecast for " + username + "(" + http.STATUS_CODES[res.statusCode] + ")"});
Also could you get away with the following with https?
var request = http.get("http://api.zippopotam.us/us/" + zip, function(res){
Also try extracting the printer methods in another file and include them in to zipcodes.js.
You may want to extract this:
//Request info from forecast.io api
var request = https.get("https://api.forecast.io/forecast/(api key)/" + latitude + "," + longitude, function(res) {
var body = "";
//Read the data
res.on('data', function (chunk) {
body += chunk;
});
res.on('end', function() {
if(res.statusCode === 200 ) {
try {
//Parse the data
var weather = JSON.parse(body);
//Print the data
printMessage(city, weather.currently.temperature, weather.minutely["summary"]);
} catch (error){
//Parse error
console.error("There was an error parsing the forecast data - " + error);
}
} else {
//Status Code Error
printError({message: "There was an error getting the forecast for " + username + "(" + http.STATUS_CODES[res.statusCode] + ")"});
}
});
...in to it's own function like getForecast so it's not so nested.
Keep up the good work!
Robert Richey
Courses Plus Student 16,352 Pointssure is a feel good moment when I make independent decisions that align with others - getForecast. Also, I just checked and https is supported for https.get("https://api.zippopotam.us/us/")
Steven Byington
13,584 PointsAndrew,
Thanks for the feedback! Https does work, so I will switch over to that. I will also go back over the getZip function to see how I can successfully split it up. I originally had two functions (getZip and forecast), but was having trouble returning an object holding the latitude and longitude info, and using it in the forecast function. I will keep working on it, and see what I come up with. Also, I really enjoyed the course. It was a great way to see a little of what node.js can do.
Aaron Musk
1,158 Pointshere's my answer:
forecast.js
var https = require('https');
// var API_KEY = "your key here";
function printForecast(summary,temperature){
console.log("The forecast summary : " + summary + "\nTemperature : "+ temperature + "");
}
function printError(error){
console.log(error.message);
}
// var latitude = 37.8267;
// var longitude = -122.423;
function get(latitude, longitude){
var req = https.get("https://api.forecast.io/forecast/API_KEY/"+ latitude +","+ longitude +"", function(res){
if(res.statusCode == 200){
var body = "";
res.on("data", function(chunk){
body +=chunk;
});
res.on("end", function(){
try{
var fc = JSON.parse(body);
printForecast(fc.currently.summary, fc.currently.temperature);
}catch(e){
printError(e);
}
});
}
});
}
module.exports.get = get;
zipcode.js
var forecast = require('./forecast.js');
var http = require('http');
function printError(error){
console.log(error.message);
}
// var zipcode = "85719";
function get(zipcode){
var req = http.get("http://api.zippopotam.us/us/"+ zipcode +"", function(response){
if(response.statusCode == 200){
var body = "";
response.on("data", function(chunk){
body +=chunk;
});
response.on("end", function(){
try{
var geo = JSON.parse(body);
forecast.get(geo.places[0].latitude, geo.places[0].longitude);
}catch(e){
printError(e);
}
});
}
});
}
module.exports.get = get;
app.js
var zipcode = require('./zipcode.js');
var zip = process.argv[2];
zipcode.get(zip);
Chris James
19,102 PointsNice. Works like a charm
Andre Rogers
2,842 PointsHow do I get my unique API key? How do I know which sites provide such information?
Andrew Chalkley
Treehouse Guest TeacherForecast.io > Forecast.io API > Register
Steven Byington
13,584 PointsSteven Byington
13,584 PointsRobert,
Looks great! I was just about to start working on separating getZip into 2 functions. I originally had 2 functions, getZip and forecast, but was having problems getting the latitude, longitude, and city info into the forecast function. I was trying to return an object with the properties, but wasn't successful. Your way makes a lot of sense. Thanks for the feedback!