Heads up! To view this whole video, sign in with your Courses account or enroll in your free 7-day trial. Sign In Enroll
Well done!
You have completed JavaScript Data Fetching!
You have completed JavaScript Data Fetching!
Preview
Learn what promises are, why they’re useful, and how they make asynchronous code cleaner. Practice creating, chaining, and handling promises.
Resources
Related Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign upRelated Discussions
Have questions about this video? Start a discussion with the community and Treehouse staff.
Sign up
Before we jump into the Fetch API,
we need to understand
0:05
something extremely important
in modern JavaScript, promises.
0:07
Fetch is completely built on promises,
so let's break this down.
0:12
A promise is an object
that represents a value
0:16
that will be available
sometime in the future.
0:19
It's a promise
that it'll be something else soon.
0:22
Up until promises,
the traditional way of handling
0:25
asynchronous code in
JavaScript was using callbacks.
0:28
Callbacks work,
but they can get messy quickly, especially
0:32
when you have multiple asynchronous steps
depending on each other.
0:35
That leads to something we call callback
hell.
0:39
Let's say we have this function, which
gets a list of breeds from the dog API.
0:43
It takes in a callback function
as an argument.
0:47
And right here,
after we successfully retrieve
0:50
our list of breeds, we call that callback,
passing in the breeds as an argument.
0:53
This is what could potentially happen
with only using callbacks.
0:58
So here, we're calling that get breeds
function
1:02
we just saw and defining our callback
that we're passing as an argument.
1:04
But sometimes, to get certain data
like specific images,
1:08
you need to call
another endpoint on the API.
1:11
So we create another function elsewhere
responsible
1:14
for fetching that data,
and we call in our callback here.
1:17
It takes in a specific breed
and another callback
1:21
to handle the functionality
once we get that data back.
1:23
So once that data has returned,
we call its callback
1:27
sending the image we received back here
and use that as an argument
1:30
to yet another callback function and well,
you see where this is going.
1:34
Right?
1:39
Could you imagine
trying to debug a program
1:40
with a collection
of nested callbacks like this?
1:42
Yikes.
1:45
Enter promises.
1:47
Promises fix this by
1:48
giving us a cleaner, chainable way
to handle asynchronous steps.
1:50
It keeps our functions separated
and our calls in a linear chain
1:54
so things are readable, easier to follow,
and in turn, easier to debug.
1:57
A promise can be in one of three states.
2:03
Pending,
the asynchronous task hasn't finished yet.
2:06
Fulfilled, the task finished successfully,
or in other words, the promise resolved.
2:09
And rejected, the task failed,
2:15
or in other words, the promise rejected.
2:17
Imagine ordering a pizza for delivery.
2:20
You place the order, and they promise you
a pizza in your near future.
2:23
The promise is pending.
2:26
Eventually, the pizza arrives.
2:28
The promise is fulfilled.
2:30
Or the restaurant cancels your order
because they don't make a peanut
2:32
butter and chocolate pizza.
2:35
The promise is rejected.
2:37
Let's open up our workspace
and play with this example a bit.
2:39
Go ahead and click the launch
workspace button below the video now.
2:42
Alright.
2:46
Let's go into this JS
directory here and open promises dot JS.
2:47
Now you won't usually create promises
manually because most modern APIs already
2:52
return them, but knowing how they work
is extremely helpful.
2:57
So let's make a tiny example.
3:00
As stated earlier,
a promise is like a placeholder
3:02
for something
that will happen in the future.
3:05
So let's store this in a variable
so that we can use it later.
3:07
I'll say const order pizza.
3:11
So this represents the promise of a pizza
being ready.
3:13
To create a promise, we use the new
keyword and call the promise constructor.
3:17
This constructor takes a function,
so let's create
3:22
an anonymous arrow function.
3:25
This function requires
3:32
two arguments, resolve and reject.
3:33
Resolve is called
when everything goes right.
3:37
Reject is called
when something goes wrong.
3:39
Inside this
3:42
function, let's add a console log
to let us know it's in the works.
3:43
Console dot log
3:46
making your pizza.
3:49
Now since we're doing this
3:54
locally, we're going to create a hard
coded status here.
3:55
Let's test it with a success first.
3:59
So let's create
a variable, const pizza success,
4:01
and we'll set it to be true.
4:06
Okay.
4:10
Now we need to tell the promise
what to do when it succeeds or fails,
4:10
so let's write a conditional.
4:14
If pizza success, meaning this is true,
4:16
we call resolve
4:23
and pass a message
like your pizza has arrived.
4:25
Else, if pizza success is false,
4:35
we call reject and pass a message
like, sorry.
4:38
Something went wrong with your order.
4:41
So these messages
4:47
will be the promise's value once
it's either resolved or rejected.
4:48
Okay.
4:53
Now let's simulate some waiting, like our
pizza is being prepared in the kitchen.
4:54
We can do this by wrapping
our conditional inside a set time out.
4:58
This is actually another example
of an asynchronous function
5:02
because it delays the execution
without freezing the rest of our code.
5:06
The program could keep running other tasks
while we wait,
5:10
if we had other tasks, that is.
5:13
So set time out
also takes a function to execute
5:16
after the wait time,
so let's wrap it around our conditional.
5:19
Let's tab this over,
5:23
and let's give it a three second delay.
5:29
We need to state this in milliseconds,
though, so 3,000.
5:31
So after three seconds,
5:39
it will check
if pizza success is true or false.
5:40
If it's true, we call resolve.
5:43
If it's false, we call reject.
5:45
So that's the creation of a promise.
5:48
Like I said, this is what you normally
won't have to do yourself,
5:50
but it's nice to see how it works.
5:53
Let's get into what you will regularly
be doing with promises, using
5:55
or consuming them.
5:59
So to start, we'll access our
6:01
order pizza promise variable.
6:03
Now that we have our promise,
6:07
we can consume it
by chaining certain methods.
6:08
The two you'll use
most often are then and catch.
6:11
We use then to handle the case
when the promise is fulfilled
6:15
or resolved successfully,
and catch to handle the case
6:19
when the promise is rejected or something
goes wrong.
6:22
So let's chain a then method call here.
6:26
We'll pass then an arrow function.
6:29
This will take the fulfillment value,
this message up
6:31
here, as an argument,
and I'll just name it message.
6:34
In the function, let's simply log
this value
6:38
to the console.
6:40
Now we can chain on our catch method.
6:44
And instead of creating one
very long line of code,
6:47
we can actually separate these across
multiple lines for readability.
6:49
Let's pass it an arrow function
like before, and also
6:57
like before, it will take the rejection
value as an argument.
7:00
I'll name it error, and let's console dot
error it
7:03
this time.
7:07
Okay.
7:13
Let's save our file
and head down to the console.
7:13
If you don't see your console,
you can go to view, show
7:16
console.
7:18
Let's run it.
7:24
So we'll do node,
7:25
and we're in the root here,
so we need to access the JS directory,
7:26
then promises dot JS.
7:30
Making your pizza,
7:33
and great.
7:36
After three seconds,
our pizza arrived. Wow.
7:37
I wish that's
how things worked in the real world.
7:40
So we got our success message
because our hard coded variable up
7:43
here is set to true.
7:47
Therefore, resolve was called,
7:48
which eventually means our
then method was run down here.
7:50
Let's change this
to false to simulate an issue.
7:54
Save,
7:57
and I'll use the up
8:01
arrow and run this again.
8:02
As expected,
we get our unfortunate error message.
8:07
So, again, resolve marks
the promise as successful
8:10
and then reacts to that success.
8:14
Reject marks the promise as failed,
and catch reacts to that failure.
8:16
One of the biggest benefits of promises
is this chainability.
8:21
I'm not sure if that's a word,
but you get what I mean.
8:25
So this earlier example
of falling into callback
8:28
hell could instead
be handled more like this.
8:31
We can chain as many
then methods as we want, and each one
8:34
waits for the promise before it.
8:37
This is why promises make asynchronous
code much easier to structure.
8:39
Alright.
8:44
Now that you understand the basics of how
browsers and servers communicate over
8:45
HTTP, how we can recreate those requests
manually with JavaScript using XHR,
8:49
and how to handle the responses
asynchronously with promises,
8:55
we're finally ready for the tool
that brings all those ideas together.
8:58
Fetch takes everything we've learned, HTTP
methods,
9:02
URLs, headers, XHR behavior,
asynchronous operations, and promise
9:06
handling and abstracts all the complexity
into a single, easy to use function.
9:12
So now that you have the foundation,
I feel a lot better about introducing
9:17
you to it.
9:21
You need to sign up for Treehouse in order to download course files.
Sign upYou need to sign up for Treehouse in order to set up Workspace
Sign up