So in the last lecture, we did a simple AJAX call
to fetch data from a country's API.
So we created a function for that.
And as we call the function multiple times,
multiple AJAX calls were made at the same time.
So they were basically running in parallel.
And we could not control which one finished first,
remember that?
However, in this lecture,
let's create a sequence of AJAX calls,
so that the second one
runs only after the first one has finished.
And here's what we're gonna do.
So in the countries data here,
there is some property of the bordering countries.
So you see, this one here has the code ESP,
which stands for Spain.
And so that's because Spain
is a bordering country of Portugal.
And so what we will do now
is after the first AJAX call is completed,
we will get this border.
And then based on this code,
we will also render the neighboring country
right here besides the original country.
And so in this case,
the second AJAX call really depends on the first one,
because the data about neighboring countries,
is of course a result of the first call.
So without the first call,
we wouldn't even know which data to fetch,
in the second call.
And so what we need to implement is a sequence of AJAX call.
So here, I already copied
the function from the last lecture, which is still up here.
And so let's call this one here now,
getCountryAndNeighbor.
So, again, we get the country as an input.
And then here, we do the first AJAX call.
And then once the load event is fired,
when the data arrives, we then handle that data.
And so everything that we have here is still the same.
Now, we will do this part here another time.
So basically, once the neighboring country arrives,
we also will want to render this one.
And so let's export this functionality
into its own function.
So that we don't have to copy it later.
And this also makes this function a little bit cleaner.
So renderCountry, that's gonna be a function,
which simply takes in some data.
And select this, we don't have to change,
the variable names in here.
And so now here, let's then actually call that function.
So renderCountry with data.
And now we get this error here,
because of course, this function no longer exists.
So getCountryAndNeighbor.
So as I save this now, this should look the same as before.
And so indeed it does.
But now here, let's actually get the neighbor country.
So let's write that, Get neighbor country.
And here actually, let's also do some comments now.
So Render country 1, let's say.
And here I will say, AJAX call country 1.
So the neighbor country will then be country 2.
So the neighbor is gonna be data.borders, I believe.
So let's just check that here again.
And so this is actually an array.
And so we will simply render the first element.
So in the case of Portugal, there is just one border.
But in other countries, like Germany,
there's like 10 borders or something.
So let's just destructor here,
basically just take the first element.
But of course, there are also countries
which have no neighbors at all.
So islands, basically.
And so for these cases,
let's simply make sure that we don't run into any mistakes.
And so in that case, we simply return immediately.
But of course, if the neighbor does exist,
then now we can do the second AJAX call.
And so let's copy all of this.
And so here AJAX call 2
and now here of course we don't want to use the country,
but he wants to use the neighbor.
But there is one particularity about that
because here the border.
So this one here, this country,
actually doesn't come with the name of the country.
But with this code.
But using our API, we can actually also search by the code.
So, right here we have that.
So right now we are using the name.
But as I said, we can also search for the code.
And so all we have to change is basically here,
from name to alpha.
So that's alpha here, and then here, the neighbor.
And so now just like before, we have to then list them
for the load event on this new request.
And let's call this request 2,
because of course, we can't do that on the same request
that we did here in the beginning.
So request 2 addEventListener.
Load, and then, or callback function.
And so you're starting to see now that the second AJAX call
now in the way we are setting it up here
is really dependent on the first one.
So that's because basically we are firing of,
the second AJAX call here, in the callback function
of the first one, right?
So basically, inside of this callback function,
we are now adding a new EventListener for the new request.
And so here, we now have
one callback inside of the other one.
And so we will talk about that
once we have this code working.
But for now, let's actually take a look at the result here.
And so that's gonna be, request
or actually just a disk keyword.
So this.responseText.
So let's see.
And, indeed, now we get data about Spain.
And no matter how many times we reload the page,
it will now always, always appear after Portugal.
Because there is no way that this AJAX call here can be made
before the one on Portugal.
Okay, and so now, well, let's just do the same
as we did here.
So we don't need this,
let's say data2 should be JSON.parse, and then this.
And of course, we need to also the destructure it then,
logging into the Console.
But now we get some error here.
So let's just take a look at the result itself
without any destructuring.
Oh, and so now it works.
And the reason for that is that the response of this API
is actually no longer an array, when we search for the code.
So here we have this alpha, remember,
and so this time, we are searching for country codes,
and not for country names.
And so the country codes are unique.
And so therefore, they can always just be one result.
And so that's the reason why no array is returned.
And probably it says here so, in the documentation.
Well, it doesn't say so.
But if we would have just simply inspected
the response here,
then we would have understood that as well.
But anyway, now it worked.
And so let's now render, this country here as well.
So data2 and now let's wait, and there it is, great.
Now Actually, I created a special class,
here for the neighboring country,
so that it appears a little bit smaller.
And so when it is the neighbor,
we want to attach some class here to the country.
And so let's pass that class in.
So let's say className.
And by default, we set it to nothing.
So here, we will just edit to the string, like this.
And now when it is a neighbor,
we can just pass in, neighbor like this.
Give it a safe, and yeah, so that looks a bit nicer.
We get information that this is a neighbor country.
And so now let's try this, for example, for the USA as well.
But now I just want to do one at a time.
So here we should probably get Mexico or Canada.
And indeed, here it is.
Here is Canada, the neighboring country of the US.
And so one more time.
This second AJAX call would not have been possible
without the first one.
Because otherwise, how would we know
that the second country here needed to be Canada?
So, again, we have one AJAX call here
that depends on another one.
And so what we have here is one callback function
inside of another one.
So you see here, we attach the first callback function.
And then inside of that, we have yet another one.
So in other words, here, we have nested callbacks.
But now imagine that we wanted
to do more requests in sequence,
like the neighbor of the neighbor of the neighbor,
and like 10 times over.
So in that case, we would end up
with callbacks inside of callbacks inside of callbacks,
like 10 times.
And actually, for that kind of structure.
And for that kind of behavior, we have a special name.
And that special name is callback hell.
So basically, callback hell
is when we have a lot of nested callbacks
in order to execute asynchronous tasks in sequence.
And in fact, this happens for all asynchronous tasks,
which are handled by callbacks.
And not just AJAX calls.
So for example, let's say we have a set timeout function.
And then here, we want to log something to the Console,
like 1 second passed, but then also,
we want to start another timeout.
Let's just set 1000 here.
So let's copy this one here.
And so as I just said, let's say,
that here we wanted to start a new timer
after the first timer has finished.
So here, we can say 2 seconds passed.
And we can even add another one.
So never mind about what just happened in the Console.
And here, why not add yet another one?
And so now they should appear like one, two, three, four.
And so here to of course, we have callback hell.
And in fact, callback hell is pretty easy to identify
by this triangular shape that is formed here, you see that.
And also the same is starting to appear here.
So if we had more callbacks in here,
then we would start to see a lot more indentation here.
And then this triangular shape, would also appear there.
Now, the problem with callback hell
is that it makes our code look very messy.
But even more important,
it makes our code harder to maintain,
and very difficult to understand, and to reason about,
and code that is hard to understand
and difficult to reason about.
Will have more bugs, and it's just worse code.
So this is a great rule
that you should always remember and keep in mind.
So again, the rule is that code that's hard to understand,
is basically bad code, because it will have more bugs,
because the harder it is to understand code
and to reason about the code,
the more difficult it will be to add new features
and to add more functionality to the application.
But anyway, given all these problems with callback hell,
we of course, need a way to solve callback hell.
And fortunately for us, since ES6,
there is actually a way of escaping callback hell
by using something called promises.
And so let's now take the next step
in our journey of asynchronous JavaScript,
which is to learn all about promises.