4.15 Weather App With Promises

Rewrite the entire program using another module that supports promise and does HTTP requests.

Let’s get started from the following

const yargs = require('yargs');
const argv = yargs
.options({
a: {
demand: true,
alias: 'address',
describe: 'Address to fetch weather for',
string: true
}
})
.help()
.alias('help', 'h')
.argv;

AXIOS
The module we are going to use is from https://www.npmjs.com/package/axios

Install
npm install axios --save

To make a get request, we use axios.get(geocodeURL).

Advantages of Axios:

response.data

axios.get(geocodeURL).then((response) => {
console.log(response.data);
});
$ node app-promsie.js -a uwaterloo
{ results:
[ { address_components: [Array],
formatted_address: '200 University Ave W, Waterloo, ON N2L 3G1, Canada',
geometry: [Object],
place_id: 'ChIJ_8ztAq32K4gRF44mljnynd0',
plus_code: [Object],
types: [Array] } ],
status: 'OK' }

This is the exactly the same as we get from the result in other modules.

$ node app-promsie.js -a 000
{ results: [], status: 'ZERO_RESULTS' }

The information of success and failure is important to make if statements.

If the URL is not correct, we get e.code === 'ENOTFOUND'. This is known through experiment.

Since it doesn’t trigger catch block if our API is right but the address is wrong, we want to re-throw another exception if the address has zero results.

if (response.data.status === 'ZERO_RESULTS') {
throw new Error('Unable to find that address.')
}

Then it will run down below to .catch(e). Then we catch that in this way

.catch((e) => {
if (e.code === 'ENOTFOUND') {
console.log("Unable to connect to API servers.");
} else {
console.log(e.message);
}
})

Final Code

const yargs = require('yargs');
const axios = require('axios');
const argv = yargs
.options({
a: {
demand: true,
alias: 'address',
describe: 'Address to fetch weather for',
string: true
}
})
.help()
.alias('help', 'h')
.argv;
var encodedAddress = encodeURIComponent(argv.address);
var geocodeURL = `https://maps.googleapis.com/maps/api/geocode/json?address=${encodedAddress}`;
axios.get(geocodeURL).then((response) => {
if (response.data.status === 'ZERO_RESULTS') {
throw new Error('Unable to find that address.')
}
var lat = response.data.results[0].geometry.location.lat;
var lng = response.data.results[0].geometry.location.lng;
var weatherURL = `https://api.darksky.net/forecast/a4fdda5fd0d59408f5addb4bd022a199/${lat},${lng}`
console.log(response.data.results[0].formatted_address);
return axios.get(weatherURL); // need another then to handle this promise
}).then((response) => {
var temperature = response.data.currently.temperature;
var apparentTemperature = response.data.currently.apparentTemperature;
console.log(`It is currently ${temperature}. It feels like ${apparentTemperature}`);
})
.catch((e) => {
if (e.code === 'ENOTFOUND') {
console.log("Unable to connect to API servers.");
} else {
console.log(e.message);
}
})