Jonas: In the last video,
we got a glimpse into Callback Hell, and it was not pretty.
So in this lecture,
let's learn about a modern JavaScript feature
called Promises,
so that we can escape Callback Hell.
However, before we learn about promises,
we should actually see one.
And so let's now replace the old XML HTTP request function
with the modern way of making AJAX calls,
and that is by using the Fetch API.
So let me go up here to our first function,
and I will just copy all of this
just to see how it used to work and how we can do it now.
Okay.
So, this is how we used to do it,
and now all we need to do is to call Fetch,
and then with our URL,
so let's just grab that part and then specify Portugal,
and that's actually it.
All we have to do now
is to store the result into a variable,
and let's still call it "request" here.
Now, there are actually some more options
that we can specify here in the Fetch function if we'd like,
but to make a simple get request like this one,
all we really need is to pass in the URL and that's it.
So for more complex AJAX calls,
the Fetch function can take in
like an object of options as well.
But again, for now, we don't need that.
But anyway, let's now give it a safe,
and well, we should also log the request to the console
to see what happens.
And so you see that the Fetch function
immediately returned a promise here.
So as soon as we started the request,
we stored the result of that into the request variable.
And then as we logged it,
we immediately got the promise here.
So let's do that again.
And again, right away, we got something called promise.
And here, it says "pending."
So if we open that up, then here it says "fulfilled."
Then we also have like a value here,
but I'm not gonna go into full detail just yet.
So what matters here is that now,
we actually have a promise,
and so this promise is right now stored
in this request variable.
But now, what exactly is a promise,
and what can we do with it?
Well, let's find out.
So, the formal definition of a promise
is that it's an object
that is used basically as a placeholder
for the future result of an asynchronous operation.
And if that sounds weird to you,
we can also say that a promise is like a container
for an asynchronously delivered value.
Or even less formal,
let's say that a promise is a container for a future value.
So there you go.
That's the most distilled down definition
of what a promise is.
So a container or a placeholder for a future value.
And the perfect example of a future value
is the response coming from an AJAX call.
So when we start the AJAX call, there is no value yet,
but we know that there will be some value in the future,
and so we can use a promise to handle this future value.
And don't worry,
this will really make sense once we go back to code.
But to understand this concept even better,
I like to use the analogy of a lottery ticket.
So a promise is just like a lottery ticket.
So when I buy a lottery ticket,
essentially, I buy the promise
that I will receive some amount of money in the future
if I guess the correct outcome, right?
So I buy the ticket now
with the prospect of winning money in the future,
and the lottery draw,
which determines if I get the money or not,
happens asynchronously.
So of course I don't have to drop everything
and keep waiting until the lottery draw happens, right?
Now, in case I did get the correct outcome,
then I will receive my money
because I have my lottery ticket,
which is the promise that I bought.
Now, what's the big advantage of using promises?
Well, there are two of them actually.
First, by using promises,
we no longer need to rely on events and callback functions
to handle asynchronous results.
Events and callback functions
can sometimes cause unpredictable results.
And so this is a big win already.
But even better, with promises, we can chain promises
for a sequence of asynchronous operations
instead of nesting like we did in the last video.
And with this, we can finally escape Callback Hell,
which was our initial goal all along.
And by the way, promises are an ES6 feature,
so they became available in JavaScript in 2015.
And so by now, they are widely used by everyone.
Now, since promises work with asynchronous operations,
they are time sensitive,
so they change over time,
and so promises can be in different states,
and this is what we call the life cycle of a promise.
So in the very beginning,
we say that the promise is pending,
and so this is before any value
resulting from the asynchronous task is available.
Now, during this time,
the asynchronous task is still doing its work
in the background.
Then when the task finally finishes,
we say that the promise is settled.
And there are two different types of settled promises,
and that's fulfilled promises and rejected promises.
So a fulfilled promise,
is a promise that has successfully resulted
in a value just as we expected.
For example, when we use a promise
to fetch data from an API,
a fulfilled promise successfully got that data,
and it's now available to being used.
On the other hand,
a rejected promise means that there has been an error
during the asynchronous task.
In the example of fetching data from an API,
an error would be, for example, when the user is offline
and can connect to the API server.
Now, going back to the analogy of our lottery ticket,
the lottery draw is basically the asynchronous task,
which determines the result.
Then once the result is available,
the ticket would be settled.
Then if we guessed the correct outcome,
the lottery ticket would be fulfilled and we get our money.
However, if we guessed wrong,
then the ticket basically gets rejected,
and all we did was waste our money.
Now, these different states are very important to understand
because when we use promises in our code,
we will be able to handle these different states
in order to do something as a result
of either a successful promise or a rejected one.
Another important thing about promises,
is that a promise is only settled once,
and so from there, the state will remain unchanged forever.
So the promise was either fulfilled or rejected,
but it's impossible to change that state.
Now, these different states that I showed you here
are relevant and useful
when we use a promise to get a result,
which is called to consume a promise.
So we consume a promise when we already have a promise.
For example, the promise that was returned
from the fetch function
right at the beginning of this video, remember?
But in order for a promise to exist in the first place,
it must first be built.
So it must be created.
In the case of the fetch API,
it's the Fetch function that builds the promise
and returns it for us to consume.
So in this case,
we don't have to build the promise ourselves
in order to consume it.
Now, most of the time,
we will actually just consume promises,
which is also the easier and more useful part.
And so that's what we will do in the next couple of videos.
But sometimes we also need to build a promise
and not just consume it.
And of course, we will also learn
how to do that a bit later.
All right, and so now,
let's actually start using promises in the next video.