[BELL RINGS]
Hello and welcome to module three
of working with data and APIs in JavaScript.
So I just wrapped up module 2, the second part,
with a project called the Data Selfie App.
And there were some new things hopefully to you
that you learned and are excited to apply
in future projects like server side programming
and GET requests and POST requests and saving
data to a database, all of the things.
But I think there are some key elements of building a web
application that involves data from external API and server
side and client side that I missed.
One of the most crucial things I think
is making an API request to an external data
source from the server, and there
are a variety of reasons why you might want
to do that or need to do that.
And I really want to demonstrate that in this new project called
The Weather Here.
The original Weather Here project
is once again by Joey Lee and was
built for a course called Quantum Humanists at NYU,
where I also teach.
In Joey's project, the user arrives on a web page.
There's information about latitude, longitude.
We know how to do that already.
There's information about the current weather and air
quality.
This will be new that we want to add
and then a big Check In button.
So a press Check In button, all that information is logged
to a database, and then there's also
a view where you can view all the different check ins
plotted on a map with leaflet.js.
Most of the functionality that I need for this Weather
Here app we already have it from the data selfie app,
but we can start with this baseline of code from there.
But there are some new things that I want to demonstrate
to you in this project.
So number one is I want to add connected to external API.
So we're going to use two different APIs--
one for weather information, one for air quality.
One of those APIs going to require an API key and not
actually even allow us to connect from the client side.
So we're going to have to look at, well,
how do I connect to an API from Node
but then have the client build display that information?
So that's going to be a key new thing.
Now I also want to figure out how do I hide the API key.
So if I want to open source and publish my code
but I don't want include my API keys, how do I do that?
So that's going to be an important piece of this
as well.
This project also allows us to kind
of play with our logs page, and let's look
at instead of just a list of all the information
in the database, how do we pull a bunch of records
from the database and plot them on a map?
And mostly, we can pull from the previous example
I made with the International Space Station
to create a map with leaflet.js.
And finally, before I go, before this series wraps up,
I really think it's important to talk
about deploying a project into the real world, so to speak.
So right now, I'm tinkering and playing around,
developing the service running here, the clients running here.
This is just all contained within my laptop.
But if I want to deploy this project to a server
so that it can live on the web that many people could access
that share of the data, participate in,
and view the website, essentially.
How do I do that?
So we're going to look at a few different options
for deploying your project onto the web.
Hopefully, I'll give you some pointers.
It is an option where you can do that for free
as well as if you have a larger project, what
sort of considerations are for our hosting services
and paying for hosting.
So this is where I'm going to begin.
I've got just sort of the very basic functionality
from the data selfie app.
I stripped away p5, the webcam images, a lot of stuff.
The page just loads and shows my latitude and longitude.
When I click Check In, it's saving that current latitude
longitude and the timestamp to the database.
And when I go to View Check Ins, I
see a login of all of my recent check ins
at this latitude, longitude, and time.
So the very first thing that I want to do in this series now
is add weather.
I want to build this display on this Page information
about the current temperature outside at this latitude
and longitude.
Now I have to figure out where I can get the weather
information from.
So I don't really feel so inclined
to build my own set of sensors in my own weather station.
So most likely, I could find some type of APIs service
that I can make a request to get the data back,
maybe even in JSON format.
This is very similar to what we did
when we looked at the International Space Station
latitude and longitude from an external API.
And there are many weather APIs, Google Weather API, JSON data.
You'll probably find a ton.
One that I've used in previous video tutorials
is Open Weather Map.
That's one that you could look into using.
The National Weather Service--
probably their other governmental organizations
or public institutions that have public weather
data that you could use that have APIs,
and you request data from.
I'm somewhat arbitrarily picking an API call Dark Sky.
What are the things I look for when trying to pick an API
is, does it have good documentation?
Are the examples easy to follow?
Can I get up and running with it fairly quickly?
And looking at Dark Sky, I find that to be
true the documentation is pretty easy to follow,
and I can get up and running with it quickly.
And it offers the data in JSON format.
While it's not entirely a free service,
it lets you do 1,000 API calls per day free,
and that's for demonstration purposes.
That's pretty much all I need.
A risk here, of course, is that by the time you're watching
this video, the Dark Sky API won't exist anymore
or the way that it works will have completely changed.
But that's just a fact.
So really, what you should be taking away from this video
is less the specifics of the Dark Sky API
but what you need to do when you find an API,
how to get your API key, how to make the request,
how to get the data and then present
the data, and hopefully, maybe follow along with this video
along but use a completely different weather API
while you're following.
So unlike the International Space API
that we looked at in a previous video,
the Dark Sky API requires you to authenticate.
It's pretty simple to authenticate.
All you need is a single API key.
Other APIs can have a much more involved process.
But if you're going to follow along and use this,
you're going to need to first go to darksky.net and click sign
up.
You're going to want to register with your email address
and make up a password.
Now I've already done that, so I'm just going
to go straight to logging in.
Once you're logged in, you're going
to arrive exactly to this page.
And you can see this is really important.
This is my API key.
It's a little bit of irony here that I've
made this public video on YouTube showing
you my API key right here.
By the time you're watching this,
I'm going to have regenerated my API key,
and this one won't be valid.
So don't try typing this one in.
You're going to need to get your own.
But while I'm making this video, this
is one that I'm going to use.
The other thing that I love about this--
already, I need to read the documentation.
But even without reading the documentation,
right here, I can see a URL for making an API call.
So if I want to get the forecast all I need is
api.darksky.net/forcast.
That's the endpoint.
We've learned about endpoints.
Now my API key and then slash latitude comma longitude.
So I can actually just click on this, open it in a new tab.
And we can see, look, this is weather
for that's a latitude and longitude for Los Angeles.
I'm getting a summary.
I'm getting near storm distance-- all sorts
information.
I can use any of this in my application.
So let's assume what I want to do
is now request this API endpoint in my client-side JavaScript.
That's the thing that we've done before.
We did that with International Space station.
So I'm going to grab this URL.
So right here, once I geolocated,
then I can say I can make an API URL, which
is equal to exactly that.
I'm going to make this a string literal because instead
of hard coding in the latitude, longitude,
I might as well say latitude comma longitude.
And then now I can say this is all stuff we've done before.
I can fetch-- make a GET request to that API URL.
So I can say the response equals await fetch API URL.
Now since I'm using the keyword await,
I need to add the async keyword up here
to this callback function.
Then I can say JSON equals equals await response.JSON.
And then I can console log the data.
So in theory, now, the feature that I've added here
in addition to geolocating, I'm going to take that geolocation,
set it to the darksky.net API, and get the weather information
back.
Let's try giving that a run--
going here to here, hitting refresh.
I'm the only person in the entire world
that's really excited to see the dreaded CORS error.
CORS stands for Cross Origin Resource Sharing.
It can be enabled or disabled.
If it's enabled, it's saying like, hey, I
want you as a separate server from a different origin
if you'll share my resources.
Now, the thing that's sort of crucial here.
If, of course, it's disabled, it's
not that the API is saying you can't have access to my data.
It's just requiring that you do it from your own server.
And this is one that's explained in the Dark Sky APIs FAQ.
If you scroll down, you'll find the question,
why do I get the error, no access control out origin?
And it's because they explain that it's for security reasons.
Because the API key is part of that request,
they want you to enforce that you can't make that request
from client side code.
You can only do it from server side code.
So this is a nice demonstration of how
we're going to make that request from node itself.
So in fact, what I want to do is take this code itself
and put it in the server.
So go to index.js, and I'm just going
to paste it in the bottom.
But where do I want to call this?
I want to make a new endpoint in my server that
receives the latitude and longitude then makes a call out
to darksky.net and then returns that
back so that I could actually have this still in my client.
I don't want to actually remove this.
What I want is to change this URL maybe
to just a local path weather slash latitude longitude,
weather being the endpoint that I'm going to create
and then console log it here.
So I'm going to go into the server.
I'm going to make a new endpoint for a get request.
I'll call that weather.
This is now a function that gets closed off like this.
And now, OK, I'm getting some errors here.
What's the issue?
This is a couple of things.
One is the argument is to the function is called response,
so I really should call that response here.
So I'm just going to call this fetch response
and then say fetch response.json.
But there's a missing piece here, actually.
Number one is this needs to be an async function
because I'm using await.
And then instead of console logging,
I want to say response.json.json.
So I'm going to make the API call from within here
and then send it back.
This is what's known as a proxy server.
It's basically the server is a proxy for darksky.net.
I can't make the call the darksky.net directly
in the client.
So I just send off the latitude, longitude, receive it here,
and make that request.
But wait a second--
how do I have these variables, latitude, longitude?
Oh boy, this is opening up a can of worms
about passing parameters with an API.
Here I am in the client side code.
I want to send to my new weather end pointthe
latitude, longitude that I've gotten from the client side
code.
Then somehow in the server, I need
to receive those and put them in here when I send the Dark Sky.
Now I need to show you how this is going to work.
But for right now, let's just make
sure this is actually working.
Let's just hardcode in the latitude, longitude.
So I'm going to go back to this particular latitude, longitude
that I know will work.
I'm going to go to my server I'm going to comment this out,
and I'm going to paste in a hardcoded latitude
and longitude.
So now when I go to that endpoint,
I don't need to pass in a latitude and longitude.
I am just going to get exactly the weather for Los Angeles.
I'm also going to do the same thing in the client.
I'm going to just temporarily comment this out and then
get rid of the latitude and longitude.
And I think for the paths to be correct,
I should have included a slash here.
OK, so let's restart the server.
Let's go to the client and hit refresh.
We didn't leave out an async function, sketch.js.
I forgot to put my async function in here.
Ah, right, let's check the server, of course.
So up here, it's going to give me a nice error that
says fetch is not defined.
Fetch is not defined.
I forgot about that.
Fetch-- the web fetch API--
is part of the client side browser API.
If I want to use it from within Node,
I can, but I need to install a Node package for that.
The package I can use to do that is called Node-Fetch.
So I'm going to go over back here
and say NPM install node-fetch.
If I go to my package.json, I can just
see that that's in there now.
And then most likely, what I need to also do
is say a const fetch equals require node-fetch,
so that's going to pull the fetch function from node-fetch.
So I can add that up here at the top,
fetch equals require node-fetch, rerun the server,
give it one more refresh here.
And there we go-- look at that.
I now have the weather from Los Angeles right over there.
The last step here--
I know this has been a bit of a longer video than usual,
but I just want to finish off this one last step--
and this last step is sending from the client
the latitude and longitude to the server,
so the server could send that latitude and longitude
to Dark Sky, get the weather, and then send the weather
backend to the client.
The way that I'm going to do that is with route parameters.
Now, we learned about routes.
If I have a GET request or a POST request,
I set up a route, a path, an endpoint
for that particular request.
Route parameters are extra parts of that path
that you can name and capture as variables, essentially,
with data that's sent from the client.
Another way to do this is with something
called a URL query string, which I cover in another video.
And so either way would work here,
but I'm going to go with route parameters.
So here on the express documentation,
we can see that a route parameter
is specified with a colon.
So the route is users.
And then I might say users slash Daniel or users slash
Schiffman, and that will come in as a user ID parameter.
So to add that, I'm going to go back to the server.
I can remove this hardcoded lat, long in
and put back in the one that has the latitude and longitude
variables.
So now, I need to add the root parameters.
So one thing I could do is I could
do slash colon lat slash colon long,
so I could have two parameters coming in.
I don't know.
I think I'm going to just make it one.
I'll call it lat long.
And then I'll send it in with a comma.
And those, you can see I haven't used this request argument yet.
This is finally a chance to use that request object.
Inside of the request object is a property called params,
and inside that params object are all of the parameters.
In this case, there's just one parameter-- something
called lat long.
So I could type in lat long, or I could also
put that I could also put that in brackets in quotes.
So either way, this will work.
I'm going to just go with the dot syntax.
And what I'm going to do is I'm going to put
that in another variable.
So I'm going to say constant lat long equals that.
And then actually what I'm going to do
is undo is I'm going to do dot split,
and I'll split with a comma.
And then the latitude is the lat long index 0.
And the longitude is lat long index 1.
So in theory, as long as I send in
as the route parameter the latitude and longitude
separated by a comma, I can pull it out of request.params,
split it by comma into an array, and put them
in each one of these variables.
So I probably should have done this more incrementally
and console log some stuff.
But let's just hope that this works.
I'm going to add some console logs to debug just so I see
in case something goes wrong.
Then I'm going to go back to the client.
Now I need to go back to the client code.
And here I can go back to this because this
is exactly what I'm sending in.
I'm going to the weather route with the parameters latitude
comma longitude.
I already set that up.
OK, let me add one more console log request.params, so we
can see the raw request params.
And let's hope that this works--
go back to the browser hit Refresh.
And there we go.
I have got the correct latitude, longitude, route
and the weather now from New York,
the actual latitude, longitude that I sent to the server.
Let's check the servers logs and there you go.
You can see, there we go.
So this is the request parameters that came in.
There was just one called lat long.
Then I used split to turn it into an array,
and then I took the 0 index of the array and index number
one of the array.
So luckily, I wrote the correct code, and it actually worked.
The next step here would be to present that information--
well, there's several next steps here.
I need to save stuff in the database
and all sorts of other things, but
the small immediate next step would
be to display the weather information here
in the DOM itself.
So I'm going to leave that for you as an exercise.
I will do that at the beginning of the next video.
And then I'm going to continue on and make a request
to Open Air Quality, the Open AQ API
to get both the weather information and the air quality
information for a single latitude and longitude.
[MUSIC PLAYING]