In this video you're gonna use the callback pattern to improve the weather application.
So in the last video we made a fake version of a geo code function which took in an address and a callback
and I got you the data when it was available.
Now we faked that by using set time out in this video.
We're going to create a real version where we actually create a HDTV request inside of the function.
Now what's that going to allow us to do.
Well it's gonna allow us to do two very important things.
One it's gonna make it easy to create code that is reusable and easy to maintain by having separate
functions we can call we can run this code as many times as we need without copying it over and over
again if I want to get the forecast in five different locations.
I just call a function five times as opposed to needing to copy all of this code and logic.
The other important thing is that it's going to make it much easier to do one thing before or after
something else.
So in this case we want to first geo code the address then I want to take the output the latitude and
longitude and use that to fetch the weather.
Now we could do this without creating our own functions but it would be pretty terrible.
We can show you what that would look like by UN commenting all of the code up above copying it to the
clipboard and pasting it in where it would be needed which is down here.
So right after we get access to the latitude and longitude I could paste all of that code in and right
away.
It's just stressful to look at.
Now if I was going to continue forward with this I would update that you are all over here concatenate
ing on those variables and that would indeed work.
There are a lot of problems with this code.
First it's hard to read and maintain.
Second it is deeply nested going up to six layers at some point which just makes code more complex than
it needs to be.
And third it's not reusable at all.
If I want to fetch the weather somewhere else I can't because it's nested inside of all of this other
code.
In reality we're trying to perform two discrete actions so we should have two discrete functions we
can use.
I'm going to undo those changes I made.
We're not going to go that route.
We're going to undo them back to the point where we had at the beginning of the video.
We have two separate requests which are currently not communicating with one another.
Let's go ahead and fix that by creating our little functions.
And together we're going to convert our geo coding example.
Then as your challenge for the video you're going to end up doing the same for our weather.
Request up above.
Let's go ahead and get started by commenting out that weather request and we're actually also going
to comment out our current geo coding request down below.
We're going to do two things.
We are going to define a function and we're going to call it.
Let's start by creating a const geo code like we did in the other file though this time it's actually
going to communicate with the map box API.
Now we still need those arguments.
So what's the input.
What do we need to geo code.
I need to know the address.
So that's going to get taken in as the first argument.
And the second is going to be the callback.
This is the function we'll call.
Once we have the latitude and longitude.
Now from here we are indeed going to call geo code.
So we're going to define this function which means we probably want to use it.
Let's go ahead and add an example call in down below passing in an address.
I'm going to use my current location Philadelphia.
Then I'm going to pass in a callback as well.
This is where we're gonna have access to the results after the geo coding process is complete when you're
working with callback functions and the callback pattern.
It's typical to see two arguments passed two callbacks and that's exactly what we're gonna do here.
You either get an error if things went poorly or you get your data if things went well.
Now this is not enforced but it is a common convention you're going to see across many different tools
utilities and libraries including what we've already seen with request if things go poorly we get an
error otherwise we get our response.
Only one of these is ever going to have a value the other will be set to undefined allowing us to conditionally
check what's going on.
Now we have to actually make sure that callback gets called with the correct arguments.
So let's go ahead and kick things off by making our request now up above.
We already have that you are well in place.
I'm gonna take the U.R.L. exactly as we have it up above not including those quotes and I'm going to
copy it to the clipboard.
So this is that you are all I should be able to paste in the browser to see the geo coding results for
the current location which is statically defined as Philadelphia.
I'm going to bring that down below and store it in a U RL variable so I'll create the variable I'll
define the string and I'll paste the U.R.L. in now the entire you are rel is gonna be static except
for this one piece right here.
This is where the address goes.
So I'm going to remove Philadelphia and I'm going to use the single quote twice.
Then I'm going to use the plus operator right here.
Now currently we're just taking the string beginning and the string end and putting them together right
in between we want to put the address.
So now we take the beginning of the U.R.L. then we have the address.
Then we have the end of the you are well and now we're gonna make a request to whatever location is
provided via that argument.
So in this case it would be Philadelphia but I could change that to New York if I wanted to geo code
somewhere else.
This is Andrew from the future with a quick update to the line.
We just wrote right here we have the before line.
This is the line we just wrote together.
We have the two parts of the U.R.L. are two strings and we can connect the address right in between.
Down below under after we have the exact same thing.
The only difference is what we're adding in between right here instead of just putting the address right
into the string we're first passing the address through a function called ENCODE.
You are a component now that function returns a string and that's going to get placed in the you are
out now in almost all situations.
You're not going to notice a difference when you run the project with these two different solutions.
The only time you're really going to notice is if someone searches for a location that contains special
characters that actually means something in a U structure.
As an example if you were to use this code up above and search for a question mark the program would
crash down below.
When we encode those special characters the question mark becomes the encoded version which for this
particular character is the percent sign then three capital F..
This is a safe U.R.L. map box is going to be able to get it decode it and handle the request correctly.
So take just a quick moment to replace address with this function call right here then test out your
code and make sure things still work as expected.
All right let's jump back into the class now that we have a dynamic you are L based off of the arguments
to the Geo code function let's actually fire off the request.
I'll start by calling request passing in the options object as the first argument we are going to set
up.
You are all property.
I have the value in the you RL variable and from there I'll also set up Jason as true making sure the
data gets passed for us.
Next up we do have to provide these second argument a function to run when the request completes.
Right here I am going to provide my function like we've done with our two other request calls and like
those calls for example.
Right here we get access to error and to response and we're gonna use both of those down below.
Now what's the next step the next step is to once again use an if statement to figure out exactly what
happened.
Did things go well.
Did things go poorly.
That's the next thing we have to do.
So right here we're going to start with an if statement I am going to check if there is an error.
If there is we are going to do something like we did before.
Now the important piece to the puzzle is the actual message up above.
We chose to log that message to the console now down below.
The goal is to create a function that is highly reusable.
When someone calls geo code they might want to do something different with the error message then log
it to the console.
Maybe they want to save it to a log file on the file system or send it to their sysadmin via an email.
Those are all things you could do with the message and it's up to geo code to be as flexible as possible.
So instead of logging out and the error we're going to pass it back to the callback the callback can
then choose what to do.
So I could call geo code five different times and do five different things with the error message.
So right here inside of the if statement what are we going to do.
We are going to call callback for the very first time in this function.
Now we know that the callback function expects two arguments.
We're gonna have an error if there is one.
Otherwise we'll have data.
Now in this case we do indeed have an error.
So we are going to provide the first argument and we're gonna provide undefined as the value for the
second right here.
Let's go ahead and set up these string.
So we are going to call the callback with a string for the first value.
Now the first argument and the first one line up.
So this is the error and we are going to say exactly what we said up above.
Unable to connect to location services.
Perfect.
So now that message is getting sent back to the caller and they can choose to do whatever they want.
Making geo code as flexible as possible.
Now remember we don't want to provide a value for that second argument if we don't provide anything
here undefined will be the value assigned by javascript.
We could always be a bit more explicit setting up undefined though both solutions would be identical.
So we've handled the if statement with the error.
Now we're going to move on to the else.
If so else if our condition and the code to run in this case we want to check if the features length
is zero meaning that we didn't get any search results down below.
Let's knock that out.
So right here.
Else if response dot body dot features dot length.
So we're looking at the length of that array equals 0.
If it does we have a problem.
What are we going to do.
We are going to call callback.
So in this case we are also trying to report an error.
So we're going to provide these string message as the first argument and undefined as the second what
do we want to say.
We'll say exactly what we said up above.
Unable to find location.
Period.
Try another search.
Excellent.
So now that we have this in place we actually have error handling all set up.
This callback would correctly get called if something went wrong with their request.
Let's test our work before going any further inside of geo code just to make sure things work.
We will choose to use console log but it's important to note that's a choice because we just get the
rostering back.
We could do whatever we want with it.
Right here I am going to print error then as the second argument I'll print the actual error message
and down below I'll do the same thing for data.
Just making sure that we're always getting the results we expected.
I'll call console dialogue with the data string then I'll actually print the data variable.
Now to test things out we want to first do something like disable our internet connection and make sure
we get that message so up above I am going to turn off my Wi-Fi and down below in the terminal.
We have to get back over to the weather app directory so S.D. dot dot to get out of playground.
Then forward slash.
Weather hyphen app.
Once I'm there I'm gonna use clear to clear the terminal output.
Then I'll run the script node space app dot J s when I run it.
What are we gonna get right here.
I get as my error unable to connect to location services and as data I get undefined which is fantastic.
That is exactly what we were looking for.
Now let's go ahead and read enable our network connection and we're going to try with a location that's
not going to return any matches down below.
I'm going to swap out New York for something else like 12 what I'm going to save app dot J S I'm going
to rerun the exact same command and what do I get.
Unable to find location.
Try another search.
So all of our error handling is done.
We can now move on to the easy part which is to set up the else clause and call the callback with the
data that we want to expose.
Now once again it's our choice.
How much of what comes back on response.
Do we want to share and the reality is we only want to share a couple of values.
I'm gonna choose to share the latitude and longitude.
And I'm also going to share one other value that came back.
If I go back to the request in the browser I can swap it out with a real search.
I'll the search for Philadelphia once again and these are the two values we're gonna start with.
And I'm also going to include the place name.
So when we print out the forecast we can include a more complete description of exactly where they're
getting the weather for.
All right let's go ahead and work on that by filling out else.
Right here we are going to call the callback and I am going to provide to it two arguments.
The first remember is where we would put the error but in this case we know there is none.
So I am going to set that value equal to undefined.
That's going to make sure that when the callback runs it does not have a value for error and it has
a value for data.
So the second argument I passed a callback that's going to be the data when things go well we're going
to provide the caller the caller down below with those three values the latitude and longitude and we're
going to provide them with a place name that label we just explored.
Let's go ahead and knock all of that out using the exact same stuff we did up above.
So first up we have latitude.
I'll set that up as a property on this object.
We know the value for that lives on response dot body dot features we're going to access the first item
in that features array and then we're going to access the center property which is an array itself and
we'll grab the first item from that which is exactly what we've already done up above.
Next up we're going to add a another property onto here longitude this value is going to come from response
dot body dot features grabbing the first one then dot center grabbing the second one.
Perfect.
This matches up with what we had up above.
Next up we're going to add that other property.
Now I could call this place name but I could also choose something that makes a bit more sense.
I'll just have location right here.
We are going to get that value from response dot body.
We still need to go into that first feature.
So dot features grabbing the first item from there we have the place name and property.
So that would be dot place name dot place underscore name.
Perfect.
Now that we have this in place when things go well when the search returns results we are going to get
that object sent back as the value for data.
Let's go ahead and see if that actually happens.
Right here I'm going to swap out 12 what with something else I'll choose to use my current location.
Philadelphia.
I'm gonna save the file.
I'm going to rerun the script from down below.
And what do I get.
I get the latitude the longitude and the label showing up.
Now if we wanted to change what we were searching for we could just update the geo code first argument.
Right here there is a Philadelphia in New York as well though it's less popular.
So I'm not going to get that back as the default result but if I do add new york on and I search for
that I can now see the latitude and longitude for that city instead.
Now we can easily call geo code more than one time to geo code from different places in our application.
We have all of that sitting behind a single reusable function we can use as many times as we need.
Let's wrap up by pulling that out into a separate file then we'll move on to the next video where you're
going to do something similar for the forecast.
I'm going to close all other files besides app dot J S I'm going to make a new directory over in weather
app which I will call you tills and in there we're going to make a single file for now.
So we will call this one something like geo code dot J.
S and all we're going to do is take the function code from over here.
We're going to remove it from Epcot J.S. cutting it out to the clipboard and we're going to paste it
over here.
Now I am going to have to require request.
We'll do that real quick const request equals what comes back from calling require and passing in the
module name then down below.
We're going to export it.
So module dot exports equals the geo code function.
Perfect.
Now this file's all done and we can easily require this anywhere we want to use it including an appetite
and J.
S Let's go ahead and wrap up by doing just that up above.
We're going to grab the constant geo code from a call to require and since we're loading in a local
file we start with DOT forward slash.
From there we want to go into the utilize directory then forward slash the file name which is geo code.
Once again leaving off the optional file extension.
Now I'm going to save things I'm going to swap out the location for somewhere else.
Let's go ahead and use something like Boston.
I'll save the file I'll rerun the script and this is going to make sure that things are still working
and right here we are getting the location information for Boston.
Excellent.
Now that we have all of this done for geo code it's going to be your job in the next video to do the
same thing for our weather request.
I'm excited to get to that.
So let's go ahead and jump right into the next video where I'll show you what I'd like you to do.