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 (2014) Building a Command Line Application Perfecting: Getting Multiple Profiles

Andrey Konovalenko
Andrey Konovalenko
9,409 Points

My solution for command line weather app using maps.googleapis.com and api.forecost.io

Hi everybody, I used maps.googleapis.com for getting latitude and longitude from google.map response object.

So your request should be: "https://maps.googleapis.com/maps/api/geocode/json?address=" + post code;

var https = require("https");
var post_code = process.argv[2];
console.log(post_code);

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

function get(post_code){
    var request = https.get("https://maps.googleapis.com/maps/api/geocode/json?address=" + post_code, function(response){
        console.log(response.statusCode);
        var body = "";
        response.on('data', function(chunk){
            body += chunk;
        });
        response.on('end', function(){
            if (response.statusCode === 200) {
                try {
                    var coordinates = JSON.parse(body);
                    var lat = coordinates.results[0].geometry.location.lat;
                    var lng = coordinates.results[0].geometry.location.lng;
                    var post_code_coord = lat + "," +lng;
                    get_weather(post_code_coord);
                } catch(error) {
                    printError(error);
                }
            } else {
                printError({message: "There was an error getting coordinates " + " (" + response.statusCode+")"});
            }
        });
    request.on("error", printError); 
    });
}

function get_weather(coordinates){
    var APIkey = 'YOUR API key';
    var options = "https://api.forecast.io/forecast/" + APIkey + coordinates+ "?units=si";
    var request = https.get(options, function(response){
        console.log(response.statusCode);
        var body = "";
        response.on('data', function(chunk){
            body += chunk;
        });
        response.on('end', function(){
            if (response.statusCode === 200) {
                try {
                        var weather = JSON.parse(body);
                    console.log(weather.timezone + " " + weather.currently.temperature);
                } catch(error) {
                    printError(error);
                }
            } else {
            printError({message: "There was an error getting forecast data " + " (" + response.statusCode+")"});
            }
        });
    request.on("error", printError); 
    });
}
get(post_code);

I will be grateful for any thoughts about improving my solution. I know I should create a object constructor for request to avoid code repetition, but I don't know good way.

3 Answers

Thomas Nilsen
Thomas Nilsen
14,957 Points

Good work! :)

I have a couple of suggestions -

  • Instead of using the http/https modules, use request. It's built on top of these modules and it's easier to use.
  • Instead of using callbacks, try to use Promises. It's very similar, but makes it easier to chain function calls (I'll post my version below).
  • Your printError() function just console.log stuff. Drop the function and just use console.log.
  • If other people were supposed to use your code (e.g. include it as a module). You should consider making the first function accept an object with params. One of the params being the API_KEY.

Here is my version of your code:

var request = require('request');

var param = process.argv[2];
var API_KEY = 'MY_API_KEY';


function getLocation() {
    return new Promise(function(resolve, reject) {
        var locationUrl = 'https://maps.googleapis.com/maps/api/geocode/json?address=' + param;
        var data = null
        return request(locationUrl, function(err, response, body) {
            if(!err) {
                try {
                    data = JSON.parse(body);

                    var lat = data.results[0].geometry.location.lat;
                    var lng = data.results[0].geometry.location.lng;
                    var coords = lat + ',' + lng;

                    resolve(coords);

                } catch(err) {
                    reject('Error during parsing of location-data: ' + err.message);
                }
            } else {
                reject('Unable to get location-data. Statuscode: ' + response.statusCode);
            }
        });
    });
}


function getWeather(coords) {
    return new Promise(function(resolve, reject) {
        var weatherUrl = 'https://api.forecast.io/forecast/' + API_KEY + '/' + coords + '?units=si';
        var data = null;
        return request(weatherUrl, function(err, response, body) {
            if(!err) {
                try {
                    data = JSON.parse(body);
                    resolve('The temperature in ' + data.timezone + ' is ' + data.currently.temperature);

                } catch(err) {
                    reject('Error during parsing of weather-data: ' + err.message);
                }
            } else {
                reject('Unable to get weather-data. Statuscode: ' + response.statusCode);
            }
        });

    });
}



getLocation().then(function(coords) {
    return getWeather(coords);
}).then(function(weatherInfo) {
    console.log(weatherInfo);
}).catch(function(err) {
    console.log(err);
});
Andrey Konovalenko
Andrey Konovalenko
9,409 Points

Thanks for response. I had no idea about existing Promise before))) I still have much to learn)

Tan Guven
Tan Guven
3,379 Points

This is my way and i like promise :) also

// app.js
const weather = require("./forecast.js");

weather.tellMeTheWeather();
// forecast.js
const request  = require("request"),
      postCode = "N101LR",
      API_KEY  = "My_API_KEY";

function weather(getLocation, coordinates) {
   function getLocation() {
      return new Promise((resolve, reject)=> {
         let locationUrl = `https://maps.googleapis.com/maps/api/geocode/json?address=${postCode}`,
             data        = null;

         return request(locationUrl, (err, response, body)=> {
            if (!err) {
               try {
                  data = JSON.parse(body);

                  let lat         = data.results[0].geometry.location.lat,
                      lng         = data.results[0].geometry.location.lng,
                      coordinates = `${lat},${lng}`;
                  resolve(coordinates);
               } catch (err) {
                  reject(`Error during the parsing of location-data: ${err.message}`);
               }
            } else {
               reject(`unable to get location-data. Status code: ${response.statusCode}`);
            }
         });
      });
   }

   function getWeather(coordinates) {
      return new Promise((resolve, reject)=> {
         let weatherUrl = `https://api.forecast.io/forecast/${API_KEY}/${coordinates}?units=ca`,
             data       = null;

         return request(weatherUrl, (err, response, body)=> {
            if (response.statusCode === 200) {

               try {
                  data = JSON.parse(body);
                  resolve(`THe temperature in ${data.timezone} is ${data.currently.temperature}`);
               } catch (err) {
                  reject(`Error happen during the parsing of weather-data: ${err.message}`);
               }

            } else {
               reject(`Unable to get weather-data. Status code: ${response.statusCode}`);
            }
         });
      });
   }

   getLocation().then((coordinates)=> {
      return getWeather(coordinates);
   }).then((weatherInfo)=> {
      console.log(weatherInfo);
   }).catch((err)=> {
      console.log(err);
   });
}

module.exports.weather = weather;
Christopher Johnson
Christopher Johnson
12,829 Points

What is the 7units=si in the var options?