In part 2 of our series, we’ll look at a website that returns random, real-world addresses, and we’ll see how we can use npm packages to issue requests to this site.
What Problem Are We Solving Again?
If you’re just joining us, here’s the problem we’re trying to solve:
Every app needs random data at some point, but what if that random data also needs to be real? That’s the challenge I ran into when generating test addresses for one of my clients. Since we wanted to plot these addresses on the map, they had to be real, physical places.
Oh, and I needed to geocode them, too, back to their lat-long coordinates.
You can also read part 1 if you want to catch up!
Getting Random Addresses
Because we want to plot these generated addresses on a map, we can’t just generate fake addresses. We need these to be real locations. There are websites out there that can help, one of which is fakena.me. They have a random US address generator that (surprise!) returns a random, valid, US address on each page load.
fakena.me provides this service for free, all they ask in exchange is to use their Amazon affiliate link to make a purchase. If you are planning on buying something today, do them a favor and use their link!
With fakena.me, we have our data source. Now we just need to hook it into our CLI app.
The App Skeleton
Let’s practice top-down design as we build out our app, and let’s pretend that we have everything already created. Here’s what our index.js would look like:
const AddressCreator = require('./AddressCreator');
AddressCreator.getRandomAddress().then(x => {
console.log(x.street);
console.log(`${x.city} ${x.state} ${x.zip}`);
});
Pretty simple! We’re just pulling in our (soon-to-be-created) AddressCreator
, asking for an address (which is an asynchronous operation, more on that in a bit!), and once the operation completes, we’re outputting the address, formatted with some ES6 template string goodness.
Let’s continue our top-down approach, and let’s make our AddressCreator class!
class AddressCreator {
static getRandomAddress() {
return Promise.resolve({
street: '123 Main Street',
city: 'Somewhere',
state: 'TN',
zip: '55555'
});
}
}
module.exports = AddressCreator;
We’re just returning a hard-coded address right now, using the handy Promise.resolve
method. Again, pretty simple!
Not up-to-speed on promises yet? Check out my series on Promises! You’ll learn about
Promise.resolve
and much more.
But what we have here is just our skeleton… how are we going to actually get addresses from fakena.me?
For that, let’s turn to npm!
The request-promise-native Package
We want to make a web request to fakena.me
in order to retrieve a fake address. For that, we’re going to install a new npm package.
One popular npm package for making web requests is request. But I don’t like request
. Most things in node like to follow the callback pattern, and request
is no exception. Well, I don’t like the callback pattern. I hate callbacks. Promises are a much more elegant solution in this case (which, by the way, can be made even more awesome by using async/await!).
Instead of using request
, we’ll use request-promise-native. This package allows us to make web requests using native ES6 promises, and yes, it will work with async/await!
One little "gotcha" to watch out for: request-promise-native
actually has a peer dependency on request
. We have to install that dependency separately.
Here’s how to install both in one call:
npm i request request-promise-native --save
Making Web Requests
Our new packages are installed, and we are now ready to make some web requests! Let’s update our AddressCreator class:
const rp = require('request-promise-native');
class AddressCreator {
static getRandomAddress() {
const requestOptions = {
uri: 'https://fakena.me/random-real-address/'
}
return rp(requestOptions);
}
}
module.exports = AddressCreator;
Now our getRandomAddress
function will make a web request and return a promise. That promise will be resolved with the result of the web request. But this is what we have in our index.js file:
AddressCreator.getRandomAddress().then(x => {
console.log(x.street);
console.log(`${x.city} ${x.state} ${x.zip}`);
});
That’s… not going to work.
We want to hand back an actual address object. As we’ve written it, our caller is actually going to get back the response of the web request.
We need to parse that response and extract the address bits out of it. And that’s exactly what we’re going to do…
… in the next post. ?
See you then!