In this video we're going to take a quick break from building out the rest api and instead we're going
to cover a more advanced promise concept.
This is promise chaining.
So we've had a dozen or so videos to work with the basics of promises.
And every time we've used them we've done just a single asynchronous thing right here.
For example we do one asynchronous thing which is to find a user by their I.D. And down below.
We also do just one asynchronous thing.
We save the new task.
What if we wanted to do one thing and then something else like geo code and address then fetch the weather
for that location or mark a task as complete and then and get the total number of incomplete tasks.
I still have to do in both of those cases we're working with two asynchronous operations where one needs
to happen and then another.
Now promises do provide an advanced syntax for actually getting that done before we worry about integrating
it into our application.
We're going to mess around with it over in the playground directory.
We have that promises file.
We've used plenty of times so far and we're going to spend a little more time in here learning this
advanced syntax as always.
Let's get started with a promise that uses set time out to simulate an asynchronous delay.
Once we're comfortable with the syntax will integrate it back into reality and use it with the promises
that Mongoose provides for the moment though we can just clean this file out and we're going to create
a new function called add add is going to take into numbers we can accept a and b as the parameters
for ADD and over going to do is return a promise after two seconds that promise will be fulfilled with
the sum.
So right here return new promise.
We are going to set up the promise function.
This is where we get access to resolve and reject.
Then we're going to wait those two seconds providing the function to run and the two thousand millisecond
delay down below.
And the last thing we put inside of here is a call to resolve and we're gonna pass in a single argument
the sum of a plus b perfect now that we have this in place.
We know how we could go through the process of using this a single time I could call add passing in
a couple of numbers I'll pass in one end to the sum being three then I can add on my then method call
to do something when the promise is fulfilled and I can add on my catch method call to do something
when that promise is rejected.
So right here I would get access to these sum and I could use it and down below I would get access to
the error and I could go ahead and just log it out now for the moment we'll also log out that sum so
console log sum.
Now I went a little quickly setting that up because this is all stuff we've done before.
From here though we'll be exploring new concepts.
Let's take a quick moment to run the program to make sure it's working before we continue on down below.
I'm gonna shut down node man which is running the task manager app I'll use CDE dot dot forward slash
playground to navigate into the correct directory then we can use node with eight hyphen promises dot
J S.
Now when I run it I would expect to wait for two seconds then see the number three print and that is
exactly what I'm getting right here.
Now in this case we are indeed performing a single asynchronous operation.
We have added two numbers together but we're going to do from here is take that sum and use it with
add again to add another number into the mix.
So that'll be two calls to add or to a synchronous operations.
Now if you didn't know about promise chaining you could still solve this problem.
You would just go where you have the sum and add a another call to add.
Where do I have the sum it's right here inside of this function and I'll add a another call to add I'll
set up the call to add I'll provide these sum as the first argument and I'll provide the other number
I'm trying to add as the second.
In this case 5 I then set up a another call to then right here I get access to what I'll call sum to
the second sum and then I could also add on a catch call to handle any errors from that.
Once again console log the error if anything goes wrong and if I do get that second some a log that
out as well some too.
So right here I've just taken another promise call and I've nested it inside of my first one.
Now if I save the program this is indeed going to work.
I can rerun the script I'll wait two seconds to see the number three and then two more seconds to see
the number eight.
And that's exactly what I get.
Now the problem with the above solution is similar to the problem we ran into when using the callback
pattern without promises.
The problem is that the more asynchronous tasks we try to perform the more nested and complex our code
gets.
For example we're doing two asynchronous tasks so we're two levels deep nested if we were to add on
a another asynchronous call it would get even more complex.
We also have duplicate code for catching errors which is not ideal either.
There's a better way to get it done using something called Promise chaining.
Let's go ahead and explore how we can recreate this example using the new syntax.
What I'm going to do is comment out the example up above the we'll leave it in place so we can compare
and contrast the two solutions to use promise chaining things start off exactly the same.
So I'm still going to call ad and I'm still gonna pick a couple of numbers to add I'll add one and one
for a sum of two right here.
I still call then and I provide my function.
Allowing me to do something when the promise is fulfilled I'll get access to the sum and I'll just keep
the examples consistent.
So right here I am going to log these sum out so we can track things as code runs.
Now we have access to the sum and we want to add that second ad call into the mix when we're using promise
chaining.
What we do is we return the next promise from our then callback.
So right here what I need to do is return a promise.
So what I'm gonna do is return whatever comes back from calling ad which I know is a promise because
I set that function up moments ago and right here what I'm gonna do is add these sum with another number.
So I have these sum which is 2.
I'll go ahead and add 4 for a total of 6.
Now the question is Where do we put our other then call in the previous example we put it inside of
the other callback and that's what created this problem where we had all of these nested callback functions
where each asynchronous process would get us further and further nested as we moved on with promise
chaining and he's second then call comes right here after the first.
So then we then get access to the result of that promise.
The result of this promise right here being fulfilled.
I'm going to call that sum too.
I'll set up my then call and right here I'm just going to console not log it to the terminal like I
had done in my example up above.
So this is promise chaining in effect it's chaining because what I'm doing is chaining together multiple
then calls each working with a different promise.
The first then call runs when this promise right here is fulfilled.
The second then call runs when this promise right here is fulfilled and we could add on a catch call
at the end to catch those errors.
So right here I'm going to provide a function similar to what I had up above but I'm going to provide
it just a single time console log.
Printing any potential errors to the screen.
Now the nice thing about promised chaining is our code is not nested.
I could chain together 400 calls to add and it would never get nested imagine 400 calls to add.
Using the example up above now 400 is a bit extreme but even with 2 it's clear that we have advantages
and if we added a third into the mix it would be even more advantageous.
Let's go ahead and run the program to make sure it's still working up and then enter.
Right here we wait are two seconds for the number two.
Then we wait two more seconds for the number six.
So right here with promise chaining we're able to achieve something similar to what we had above.
But with an improved syntax all you need to know is that you can return a promise from one of your then
callbacks allowing you to chain a another then call on.
So that is the promise chaining syntax in isolation.
Let's go ahead and actually use it with our tasks.
Now there's not a real use case for it just yet.
Inside of our rest api.
So what we're actually going to do is create a new directory any task manager folder.
Right here I'm going to create a new folder and we're going to create a playground a directory specific
to the task manager app and in there we're going to create a new file called Promise hyphen chaining
dot J S and we're going to use this file to explore how we can work with Mongoose promises any chaining
syntax.
Now we only need two things inside of here.
First up I do need to require that Mongoose file to connect to the database.
That's C D excuse me not C D.
Just dot dot forward slash source forward slash D.B. forward slash mongoose.
Now that we have the database connection we want to grab the model we'll be working with.
I'll be working with the user so I'll require that as well dot dot forward slash source forward slash
models forward slash user.
So now we have access to the user and we're gonna go ahead and use a couple of new queries that Mongoose
supports to do something interesting.
What I'm going to do is change the age for a user then I'm going to fetch the total number of other
users that have that same age.
Let's start by grabbing the I.D. of the user we're trying to update.
So over in robo 3 T we can grab any of our user I.D. I'll switch over to the table view now the age
for every single user is zero.
So it doesn't really matter which one I update I'm going to right click one of my documents click edit
document and I'm going to copy the string object I.D. to the clipboard we can bring that over to visual
studio code and I'll go ahead and just paste it right here and a comment and we'll use it in a moment.
Next up we have to figure out which Mongoose methods we're actually gonna use to get all of this done.
For that we want to head back over to the documentation in the browser and under that queries documentation
where we were before we have a few different options for doing this.
I have Update 1 and update many but I also have find one and update and find by I.D. And update now
they find variations simply return the document as well.
So these ones down below they're not going to give you the document back find by I.D. and update will
and so will find one and update.
So it's really up to you.
Which one you choose to use.
I'm gonna go ahead and use find by I.D. and update so I'll click that to get brought over to the documentation.
Now we can go ahead and actually use this.
We are going to call user dot find by I.D. and update and the first argument we provide is our I.D..
So I have the I.D. right here.
I'm going to cut it out.
Remove the extra lines and I'll paste it right inside of a string as the first argument to our method.
Now the second argument is the object which contains the updates we want to apply in this case.
I'm going to set the user's age from zero over to 1.
Now you'll notice that I'm not using that dollar sign set.
Update.
Operator we explored with the Mongo D.B. native driver the Mongoose library actually takes care of this
for us so we don't have to do that which is a nice feature.
Next up we can go ahead and use then.
So dot then to run some code when we have found an updated given document.
I'm gonna have access to that.
I can call this something like user ID down below.
All I'm going to do is print them to the console.
Excellent from here.
We want to perform that second asynchronous operation which is to count up all of the users that have
that same age so all users whose age is 1 Mongoose provides us with a method to get that done as well.
Now over and that queries documentation they show us a list of methods that are available on our model.
This is not a complete list.
This is just some of the most popular ones that are used to get common tasks done.
This is in the guides documentation which is more like a tutorial down below an API.
We get the actual implementation for every single method available.
If we click on model we can explore these as well as many others.
So I'm going to navigate over to the model API docs and down below.
We have a bunch of different ones including the one that we just used.
Find by I.D. and update sitting right here now.
The method that we're here to use is up top a little bit.
It is called Count documents.
Now we also have a count but count is deprecated and it'll be going away at some point in the future
count.
Documents is going to allow us to count up the number of documents now.
Right here we can see they have an adventure model and they're trying to find the amount of adventures
that have a type of jungle.
We're gonna do something similar but with an age of 1 for the user model over inside of promise chaining.
J.S. let's get this done.
Now remember the whole goal is to use chaining.
So I want to return the next promise.
Return user dot count documents and account documents.
Works by accepting an object.
Right here we provide our filter where age equals 1 and what we eventually get back.
The promise is fulfilled with the account.
So right here I'll add on my second then call chaining it on to the first.
I'll set up my callback function and then we're gonna go ahead and get access to the result and we'll
print it to the terminal
Excellent.
Down below.
We'll also set up a catch.
Call at the very end to handle any errors from either of those two promises up above.
Right here I'll set that up and I'll use console dot log with e to get that done.
Perfect.
So now that we have this in place we can actually test our work and make sure everything's actually
functioning down below from the terminal.
We need to navigate out of the playground directory so C D dot dot and back over to the task manager
app.
Once we're here we'll go ahead and run the new file.
That would be node playground forward slash promise chaining.
J.S..
Now when we run the script we're gonna get some interesting output.
The first thing we're gonna see is actually a deprecation warning which we'll address in just a moment.
After that we get the document that we found.
So that's printing from line 5 which looks great.
And then after that we get the number one that is the count.
There is one user with an age of 1.
It is the user that I just updated.
Now let's take another user I.D. and update them as well.
So if I refresh my data over here I can see they now have an age of 1.
I'll grab some other user with an age of 0 added them just to grab their I.D. and then we'll bring that
I.D. over to visual studio code from here.
I'll swap out the old user I.D. with the new one I'm gonna save the program and rerun it a second time.
This time we're gonna see that the count is now 2.
There are two users with the age of 1.
The one I had changed a few moments ago and the one that I changed just now.
So right here we can see how we can use promise chaining to do one thing after another.
Now let's wrap up by talking about this deprecation warning that we're getting right here.
Deprecation warning collection dot find and modify is deprecated then it offers up some alternatives
we could use instead.
So find and modify is deprecated because there's better alternatives and it's eventually going to go
away.
Now this is not something we ever typed out in our code.
It's actually coming from the Mongo D.B. native driver that mongoose is using behind the scenes.
So the Mongo DB native driver will change how things get done.
They'll deprecate old methods and introduce new ones and it takes Mongoose a little bit of time to get
up to speed.
So you'll see these warnings every once in a while.
Now it's very possible you're not even seeing this warning.
That's OK if you are you can always address it by going into Mongoose and setting up a no other option
similar to what we did with use knew you are El parser.
That means we'll be setting up a third of property on this object and this one is called use bind and
modify and that is set to true by default.
We're going to set that to false which will address the deprecation warning until it's addressed by
default.
Now if we save Mongoose dot J S we can go ahead and rerun these script down below.
By shutting it down and starting it up once again and now we have no deprecation warnings in sight which
is nice.
So at this point we've got a basic rundown on promise chaining.
It took a little while but I wanted to go through two examples one using fake asynchronous operations
with set time out and another using real asynchronous operations in the next video.
There'll be a challenge where you're gonna have to use promise chaining on your own.
I'm excited to get to it.
So let's jump right in.