[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]