Skip to content
CBT Nuggets

Intermediate Promise Concepts

This skill delves into intermediate concepts of using Promises in JavaScript, particularly within the Node.js environment. It covers creating custom Promises, handling asynchronous operations, and managing errors effectively. Learners will also explore advanced techniques such as chaining Promises, introducing delays, and converting callback-based functions to Promises. The skill culminates in a practical challenge to reinforce the concepts learned.

Full lesson from JSNAD. Preview the IT training 23,000+ organizations trust.

48m 5 Videos 4 Questions

Skill 10 of 42 in JSNAD

Creating Our Own Promises

In the previous skill, we learned the basics of using Promises to manage asynchronous logic. Ah, but where do Promises come from, you ask? That's what we're going to start off by talking about this skill. In this first video, we take a look at how to use the Promise constructor, as well as some of the finer details of when Promises actually start running the logic we give them.

Knowledge Check

The "executor" function that we create a new Promise with will be called when we ________.

  1. ACreate the promise
  2. BCall .then on the promise
  3. CCall .catch on the promise
  4. DCall .exec on the promise

Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.

Resolving and Rejecting Promises with Values

Now that we've seen how to create a simple custom Promise that just resolves (pretty boring, right?), let's take a look at how we can have our Promises reject as well. We'll also take a look at how resolving or rejecting Promises allows us to pass the resulting values to the .then callbacks.

Knowledge Check

Passing a value to "reject" will make that value show up in the callback that we pass to _________.

  1. A.catch
  2. B.then
  3. C.finally
  4. D.error

Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.

Creating a setTimeout Promise

Finally, let's get down to business and do something a little more interesting. In this video, we see how to create a custom Promise that allows us to insert delays into our Promise chains. Let's take a look.

Knowledge Check

If we want to have more control over when a custom Promise begins executing, we can simply __________.

  1. AWrap it in a function
  2. BCall .wait on the newly created Promise.
  3. CWait to call .then on the Promise until we want it to start
  4. DPut it in an object

Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.

Challenge & Solution: Promisifying Callback Functions

Now it's time for a challenge! In this challenge, you'll be asked to write some code that converts some of the fs package's functions to promises. Watch the video for more information.

Also, here's the link to the specific commit on Github in case you want to use Codespaces for this challenge.

And now that you've attempted the challenge, I'll show you how to solve it.

Knowledge Check

Is this your first time creating custom promises or using the Promise constructor?

This interactive assessment is available in the full learning experience.

Verify your team's readiness — Request a Demo to verify practice assessments, completion reporting, and CSV / SCORM exports on the Team plan.

View Transcript

Creating Our Own Promises

0:00Hi, Sean here and welcome to this skill where we're going to continue talking

0:04about how

0:05to work with promises effectively in Node.js.

0:08Now in the previous skill, which I'd highly recommend you take a look at, we

0:12learned the

0:13basics of promises and we saw how to do simple things like create chains of

0:18sequential asynchronous

0:21operations as well as things like handling errors in promises.

0:26So again, if you haven't seen that yet, you probably want to go back and take a

0:28look at

0:29that.

0:30But what we're going to take a look at in this skill is some somewhat more

0:34advanced things

0:36that we can do with promises.

0:38And while these are slightly more advanced than what we learned about

0:41previously, they're

0:42still going to be incredibly useful for you when writing Node.js code because

0:47what they'll

0:48allow you to do is actually write more reusable promise based code.

0:53You'll see what I mean by that shortly.

0:55But anyway, the first thing that we're going to take a look at here is we're

0:59going to see

0:59how to create our own custom promises.

1:03So what we'll do first here is just create a new file called custom promises

1:09dot JS.

1:09And the first thing that you should know here is that in order to create custom

1:14promises,

1:15we're going to create instances of the promise class, which is automatically

1:21included in

1:22the JavaScript runtime. So we don't need to import that like we've had to do

1:27with some

1:27other things in in Node JS, like FS, of course.

1:32So here's the basic syntax for creating our new promise.

1:36We're going to say const will say my promise equals.

1:41And then we can just say new promise.

1:45And that will create a promise for us.

1:47Now there is one notable thing lacking from this statement here.

1:52And that is we need to define what we actually want the promise to do in the

1:57first place,

1:58right? Now the way that we do this, it's a little bit strange.

2:01So just bear with me here, you'll, you'll see how this works.

2:05You'll get a sense for how this works as we go through this skill.

2:09But we're actually going to pass a function to the promise constructor.

2:14And this function is going to take two arguments itself, which are generally

2:20called resolve

2:21and reject.

2:23Now what these things do, I'll describe that much more detail shortly.

2:28But anyway, inside this promise function that we're passing, which by the way,

2:33the name

2:34of this thing, you'll see this in the promise literature, in many cases, this

2:40is actually

2:40called an executor function.

2:43I don't actually know if that's the way you pronounce it executor executor.

2:47I don't know.

2:49It sounds like a Pokemon name to me.

2:51But anyway, that's what that function is called.

2:54And the reason it's called this is because that is the actual logic that the

2:59promise

2:59is going to execute, right?

3:01So hence the name, I suppose.

3:04But anyway, inside this, whatever, whatever kind of functionality we want to

3:09write inside

3:10our promise, the important thing is that at some point we call one of these

3:16arguments.

3:17That's right.

3:18We need to actually call either resolve or reject because they are in fact,

3:23functions

3:24themselves that we can use to indicate to this promise what happened, right?

3:30What the overall result of our application or of this operation rather was.

3:37So let me just get started here by giving you the simplest case.

3:41We're just going to call the resolve function inside of this promise.

3:47And then what we're going to do is we're going to say my promise dot then.

3:51And we'll just say something like console dot log done inside of there.

3:56All right.

3:57Now what's happening here is we're creating a promise.

4:01This part might confuse you a little bit here because we've been used to seeing

4:05things

4:05like FS dot read file, right?

4:09Something that actually clearly does something.

4:11And then we can say dot then.

4:13But something that you may not have realized is that because things like FS dot

4:19read file

4:20and by this I'm referring to the promises version.

4:23So let me actually just import that here to make it a little bit more clear.

4:27We're going to say const FS equals require FS dot promises.

4:33And if we call FS dot read file, we'll just use file one dot T XT here.

4:39And then, oops, let's try that again.

4:41We'll use UTF-8 for the encoding.

4:44Well we saw that this returns a promise.

4:46So I'll just do this one more time, although I did it in the previous skill as

4:50well.

4:50If we print this thing out here, what we're going to see if we run our code

4:55with node

4:55custom promises dot JS is that that actually returns a promise with the state

5:01of that promise,

5:02which can be pending, fulfilled, or rejected in curly braces here.

5:08All right.

5:09So anyway, that's the basic idea here is that operations like this will

5:15generally return

5:16promises.

5:18But if we're defining our own promises like we are here, then we can just call

5:22dot then

5:23on the end of that promise, and that will assign a callback to it.

5:27So in this case, what we're going to do is if we if we run our code with this

5:31new custom

5:31promise that we just created, all right, and again, we'll use node custom

5:36promises dot

5:36JS for that, we're going to see that it'll just print out done, right?

5:41Very simple.

5:43But what's happening here is we're calling resolve inside this promise, this

5:49executor

5:50function.

5:51And that is telling the promise that it should call whatever callback is in the

5:58next dot

5:58then method, right?

6:01In other words, when we call resolve here, it tells my promise to look inside

6:06its dot

6:07then method.

6:08And it gets this callback, which it calls and we see done printed to the

6:12console.

6:12All right.

6:13Now, if we wanted to create a few promises here, right, we'll just say my

6:17promise, then

6:18we'll do my promise to and then we'll do my promise three.

6:23All right.

6:24Well, we can chain these together just like we saw in the previous skill just

6:30by using

6:30multiple dot thens, right?

6:32So we can say my promise dot then.

6:34And maybe we can log something out to the console here still.

6:39So we'll say something like console dot log first promise completed, something

6:46like that.

6:47And then what we'll do is we'll actually return my promise to and then we can

6:53call dot then

6:54after that.

6:55So we'll say dot then and we'll say console dot log second promise completed.

7:00Oops, there we go.

7:03And then what we're going to do next is we're going to say dot then and we'll

7:09have our last

7:11or our third promise here.

7:12What we're actually going to do is we're going to say return my promise three.

7:18And what this is going to look like is we're going to say dot then and then we

7:23'll say console

7:23dot log and we'll say third promise completed.

7:30Okay.

7:31So in this case, if we run our code, what we're going to see is sure enough, it

7:34logs out first,

7:35promise completed, second promise completed, third promise completed.

7:39And that's pretty much what we saw with running operations such as reading

7:44files sequentially

7:45using promises as well.

7:47Now one thing that's very important to realize here with our promises is that

7:53just like when

7:53we called fs dot read file, or really anything else fs dot on link, as soon as

7:59we create the

8:00promise, it's going to start running its executor function.

8:04All right.

8:05In other words, when we created these three promises, they've already started

8:11to execute

8:12their, their little executor function right here before we've even said my

8:17promise dot

8:18then.

8:19Now here's where people get confused.

8:21It certainly looks like just from the output, it certainly looks like our

8:26promises are executing

8:27sequentially, right?

8:29First promise, second promise, then third promise.

8:31But that's actually just because we're returning those promises and listening

8:37for them to complete,

8:39right?

8:40So in other words, it's a little bit confusing because a promise can have no

8:46listeners attached

8:47to it and it can complete, right?

8:50So it can jump to the fulfilled state.

8:53But then another piece of code could come along and attach a listener to it by

8:57saying

8:58dot then, and if that promise is already fulfilled, then that callback function

9:04is

9:04going to be called immediately, right?

9:06So in other words, if we add dot then to an already fulfilled promise, that,

9:11that callback

9:12is going to be called, and it's going to look like our promises only started to

9:17execute

9:18when we added dot then.

9:19So hopefully that makes sense.

9:21Let me just demonstrate this in a little bit more detail for you.

9:25What we're going to do is we're actually going to print something out inside

9:29these executor

9:30functions.

9:31So we'll say console dot log, we'll say something like promise one is starting.

9:37All right, and then we'll do the same thing for our other promises.

9:40So we'll just copy this and paste this in the other ones.

9:43We'll say promise two is starting and promise three is starting.

9:48And if we run our code again, what we're going to see is sure enough, all three

9:52of those

9:52promises start before we even see the first promise log out.

9:58Another demonstration of this just to give you another demonstration here.

10:01And for this, I'm just going to comment out all of this temporarily.

10:05But let's say that we created our own promise.

10:08Again, we'll just use const.

10:09And actually here, we'll go up and use my promise again.

10:12So that I don't have to type that out again.

10:14Let's just uncomment this.

10:15And what we'll do is we'll say set timeout.

10:18And inside here, what we're going to do is we're going to just say my promise

10:24dot then.

10:25And we're going to log something out, saying something like, you know, we'll

10:29just say console

10:30dot log inside dot then.

10:33All right.

10:35And we'll set that for maybe two seconds.

10:38But we'll also say console dot log after the resolve, we'll say something like

10:45promise one

10:46has resolved.

10:49And what we're going to do here is we're going to run our code.

10:52And sure enough, we see that it says promise one is starting, promise one has

10:56resolved.

10:57And after two seconds, we see it log out inside dot then.

11:01So in other words, clearly the promise has already finished here before this

11:07console dot

11:08log thing gets logged out.

11:10It's just that it's not until we add dot then to that promise that we see that

11:13happen.

11:14So it can definitely be a little bit confusing at first, but notice what this

11:18allows us to

11:19do, right?

11:20What we've, what we've done here when we say my promise dot then dot then dot

11:24then is it's

11:25allowed us to take three asynchronous tasks, right?

11:29Three asynchronous operations.

11:31We have no clue how long they're going to take or when they finished or if they

11:34've finished.

11:35And it's allowed us to easily organize those so that we have the results in a

11:40sequential

11:41manner.

11:42All right, and that's the real power of how promises work and how this whole

11:47resolving

11:47and rejecting thing works as well along with the dot then chain.

11:53So anyway, I hope this has made sense so far.

11:56The next thing that we're going to take a look at is how we can get a little

12:00bit more

12:00detailed and perform some more useful tasks with our promises.

12:05So anyway, I hope this has been informative for you and I'd like to thank you

12:08for viewing.

12:09[BLANK_AUDIO]

Resolving and Rejecting Promises with Values

0:00All right, so at this point, we've seen how to create a new promise with the

0:04promise constructor,

0:06but so far our promises aren't really doing anything interesting, right?

0:09They're just logging something out to the console, resolving and that's about

0:14it.

0:14So anyway, what we're going to take a look at next is how we can actually use

0:20the reject

0:21function, right?

0:22This reject argument that our promise executor function has in order to

0:27actually determine

0:29if something went wrong or determine if a promise failed and let the chain that

0:34our

0:34promise belongs to know about that.

0:37So here's what that's going to look like.

0:38First of all, I suppose let's just change my promise to and we're going to

0:43change this

0:44to call reject instead of resolve.

0:47All right, now perhaps you already know what's going to happen here.

0:50If we run our code and actually, well, I guess this is going to be kind of a

0:55spoiler, but

0:56let's just say dot catch at the bottom here and we'll just log out the error

1:01here.

1:02We'll say console dot log error.

1:04And if we run our code now, what we'll see is that it says first promise

1:08completed and

1:09then it logs out undefined.

1:11Now undefined might not be exactly what you were expecting here, but basically

1:15when we

1:15call reject, we get to pass an error message to this that will actually be

1:21picked up by

1:22the catch callback down here.

1:25So if we say something like reject, this promise is stubborn today, something

1:31like that, then

1:33what we're going to see is if we run our code here, sure enough, we see that

1:37that message

1:38gets printed out.

1:39Now this can be an actual error.

1:40If we want to say something like new error, this promise is stubborn today,

1:44something like

1:45that, then that'll work as well.

1:48And that'll just make it a little bit more detailed, right?

1:51That'll add the whole stack trace details onto there.

1:54So anyway, that's the basics of rejecting a promise.

1:59And one thing that I kind of want to go back to here is I want to show you that

2:03resolving

2:04a promise, when we do that, we can actually pass the result value to this thing

2:09, right?

2:10So in other words, let's change this down here to say something like first

2:14promise completed

2:15with the value.

2:17And then what we'll do is we'll actually make this an argument here.

2:21We'll say something like, well, we'll say result there, and we'll do the same

2:24thing down

2:25here with promise two, and we'll do the same thing with promise three.

2:29We'll just say result result result.

2:31Oops, let's try that again.

2:33There we go.

2:34And now if we say first promise completed with the value result, second promise

2:38completed

2:39will do the same thing.

2:40And in fact, I'll just copy and paste this to make it easier.

2:43And we'll change that to second promise.

2:46And then with our third promise here, we'll say third promise completed with

2:51the value.

2:52There we go.

2:53Cool.

2:54So if we go back up to our promises here, and let's change my promise to back

3:00to resolve,

3:01we can actually pass the result of whatever operation that we, that this

3:05promise is meant

3:06to represent to the resolve function, right?

3:10So we can say something like resolve one, if this one may be resolved with a an

3:15object

3:16of some sort, we could say a one, b two, perhaps.

3:21And then we could resolve my promise three with an array of some sort, right?

3:25We'll say a, b, c.

3:27All right.

3:28So what we're going to see now is if we run our code, sure enough, we see that

3:33the first

3:33promise completed with the value of one, the second value completed with the

3:37value, well,

3:38just printed out an object here, but you get the idea.

3:41And then we see that our third promise completed with the values, a, b, c.

3:46So essentially what's going on here is when we create a promise and we call

3:51resolve, and

3:52then we put that promise into a chain by calling dot then on it, the, the value

3:59that

3:59we call resolve with is going to be the argument that gets passed to the

4:04callback that we passed

4:05to dot then that's got to be about the longest, most convoluted explanation I

4:09've ever given.

4:10But anyway, hopefully you can see the connection here.

4:13This one becomes this argument in the dot then callback.

4:19All right, that's how that works.

4:20And the same thing is true for all of these as well, although it's, it's

4:24obscured a little

4:25bit by the fact that we're just returning these from the callback.

4:29But if we were to say, you know, my promise here, let's try that again.

4:34If we were to say my promise to dot then, and then we could just log that out

4:40here, that's

4:41going to give us whatever we called resolve with here, right, that result is

4:45going to be

4:46whatever we called the resolve function with cool.

4:51So anyway, that's the basics of resolving a function and rejecting a function

4:55that we've

4:56created.

4:57Let's move on now and see how we can do something slightly more interesting.

5:00What we're going to do is we're going to create a promise that has, you know,

5:05we'll say like

5:06a, we'll say that it has a 5050 chance of resolving and rejecting.

5:11So here's what this is going to look like.

5:13I'm just going to comment out all of the other code that I had above there,

5:16just so that

5:16you have it for reference in the GitHub repo.

5:20But we're going to create a promise here called something like 5050.

5:24And this is going to be a new promise.

5:26And oops, I forgot my const before that.

5:28All right, so this is going to be a new promise.

5:31And it's going to have resolve and reject as arguments, just like we just like

5:36we've

5:37seen before.

5:38And here's what this is going to look like.

5:40We're going to flip a digital coin here by using the math dot random function.

5:46And if it's above a certain value, we're going to call resolve.

5:50If it's below a certain value, we're going to call reject.

5:52So here's what this is going to look like.

5:53We're going to say, oops, there we go.

5:57We're going to say, if math dot random, and this will give us a random number

6:03between

6:03zero and one.

6:04So we can say if math dot random is less than 0.5, that'll give us about a 5050

6:11chance

6:11there, then we're going to resolve the promise with some value.

6:16We'll say something like, yay.

6:19Otherwise what we'll do is we will reject the promise with another message.

6:25We'll say something like darn.

6:27Okay.

6:28Cool.

6:29So here's how this 5050 promise is going to work.

6:31We can call dot then on it, right?

6:33We're going to say 5050 dot then.

6:38And what this is going to look like is the dot then callback, that'll just be a

6:43message.

6:43We'll say something like console dot log, and then we'll say success.

6:48And then we'll just add that message onto the end.

6:51So we'll say plus message.

6:53If it fails, though, we're going to have to catch it with dot catch.

6:57And in this case, we'll say message, and we'll say something like console dot

7:03log, and we'll

7:04say something like failure.

7:07And then we'll say plus message there as well.

7:10Cool.

7:11So anyway, let's run this code a couple times because we're going to need to

7:15run it a few

7:16times in order to see just different results.

7:19So let's run our code.

7:21Oh, it looks like it failed the first time.

7:23So it says failure darn if we run it again, we get failure again, we get

7:27success now, failure

7:29again, failure, failure.

7:31It looks like this one's failing a lot.

7:33Wonder what the chances of that are.

7:35But anyway, that is the basics of creating a promise that will succeed or fail

7:42with a

7:43about a 5050% chance and either resolve or reject in that case, right, which

7:49will then

7:49translate into either calling then or calling dot catch.

7:53So this is just a very introductory example of something that's kind of useful

7:57that we

7:57could do with a promise, right?

7:59Because what you could do here is if you needed something that would happen

8:02with a 5050 chance

8:04in your in your program, you could actually take advantage of promises syntax

8:08in order

8:09to do that.

8:11But nevertheless, we will see some more useful things in following videos.

8:16So I hope this has been informative for you.

8:17and I'd like to thank you for viewing.

Creating a setTimeout Promise

0:00All right, so hopefully at this point, you're getting a basic sense of how this

0:05new promise

0:06constructor works along with the executor function that we pass to it.

0:11So what we're going to do here is we're going to do something that can actually

0:14be very,

0:15very useful when you're working with promises.

0:17We're going to take a look at how to create a promise that will wait a certain

0:23amount of

0:23time before resolving, right?

0:26This can be very useful for doing things like introducing delays.

0:30So if you want to create some sort of web scraper that needs to wait a certain

0:33amount

0:34of time before it sends another request or something like that, this can be

0:38very useful

0:38in that kind of situation.

0:40So what we're going to do here is I'm going to actually leave this 50/50

0:45function commented

0:46out just so you have it for reference again.

0:48And underneath it, I'm going to create a promise that will wait.

0:54Let's say something like one second before fulfilling.

0:58So here's what this is going to look like.

1:00We're going to say something like delay, or in fact, we'll call it one second

1:05delay.

1:06And this is going to be a new promise here.

1:08And what that's going to look like is we're going to say new promise resolve

1:14reject.

1:15And we're going to use set timeout here in order to wait one second.

1:21So we'll say one second.

1:23And for the callback, here's what that's going to look like.

1:25We're just going to have the callback of set timeout call resolve with no

1:30arguments.

1:31Right.

1:32Now, if we wanted some kind of value there, we could always pass it, but I'm

1:34just going

1:35to leave that empty.

1:37Now, this is actually very, very simple, right?

1:41You might not have thought that it would be this simple to create a promise

1:43that would

1:44introduce a delay.

1:46But what we can actually do here is we can say one second delay.

1:50And what this is going to look like is we can say dot then, and we'll say

1:53something

1:54like console dot log.

1:57That was a long wait.

1:59All right.

2:00Cool.

2:01So if we run our code now, what we're going to see is it'll wait for a second,

2:05and then

2:05it'll print out that was a long wait.

2:08However, there is one big problem with this.

2:11And this goes back to our discussion that we've kind of looped back to a few

2:15times already.

2:16And that discussion is that promises start to execute the moment that they're

2:23created.

2:24Right.

2:25So in other words, if we had some other fairly long running operation here,

2:29right, if we

2:30had, if we were maybe reading a large file or something like that, and then

2:35here, I'll

2:35just type this out.

2:37And then we said dot then, and then we wanted to introduce a one second delay

2:43into that,

2:44that sort of pipeline there.

2:46Well, that's not going to work, right here.

2:49What we're going to do, actually, I have the syntax of that wrong, let's say

2:52return one

2:53second delay, and then we could say dot then, well, this isn't actually going

2:59to introduce

3:00a one second delay from when the large file finished reading, it's going to

3:05introduce

3:06a one second delay from when we first created this promise, right?

3:10And you can see this if you just say something like console dot log, we'll say

3:14starting time

3:15out.

3:16All right.

3:17And then we'll say console dot log time out finished.

3:23Well, I guess we're just going to have to simulate this fs dot read file thing

3:27with another

3:28time out, not my favorite demonstration there, but let's just say set timeout,

3:32and then we'll

3:33say something like a one second delay.

3:36Oops, let's try that again.

3:37We'll say one second delay dot then.

3:40All right.

3:41Well, what that's going to look like is here, let's just introduce maybe a

3:45little bit of

3:45a two second time out there.

3:48What you're going to see is that this, that was a long way thing is going to be

3:51printed

3:52out after two seconds, although many people who are new to promises would think

3:57that this

3:58would print out after three seconds.

4:01So here's what this is going to look like.

4:02And actually, just to make this a little bit more visible, let's set this to

4:05two seconds

4:05to so it's a difference of two versus four seconds.

4:10What I'm going to do now is I'm going to run the file and one 1000 to 1000.

4:15And sure enough, we see that it prints out after two seconds instead of the

4:20desired four.

4:21Okay.

4:22So that brings up this question here of if we want to have control over when

4:29the promises

4:30start, how do we do that?

4:33Well, the good news here is that the answer is actually surprisingly simple.

4:37All we have to do is make this a function that returns a promise instead of

4:44just a promise

4:45itself, right?

4:46So there's a very subtle difference there in syntax, but a very big difference

4:51in the

4:52actual outcome.

4:55If we want to, if we wanted to be able to introduce a one second delay at any

4:59point,

5:00then we're going to need to just create a function that returns this new one

5:04second

5:05delay promise.

5:06All right.

5:07So that's what that looks like.

5:08If you want to, you know, if you prefer the regular old function syntax, you

5:11could say

5:12something like this, we could say return new promise like that.

5:16That might make it a little bit more visible for you.

5:19And actually we need to say function, we'll say one second delay.

5:27There we go.

5:28And now this will actually introduce, well, I guess it's not a one second delay

5:33anymore.

5:34This will actually introduce a two second delay from when we start it, but we

5:38do have

5:38to change the syntax a little bit when we use it, we need to say two second

5:43delay with

5:44parentheses after it, right?

5:45So in other words, this will create the promise here that we can add dot then

5:52two.

5:52And oops, I abbreviated second there.

5:55So we need to remove the O and D on the end.

5:58So let's try this again.

5:59And we should see that now it will actually wait for four seconds.

6:04So here's what this is going to look like.

6:05We're going to run our code.

6:06One 1000 two 1000 three 1000 four 1000.

6:10And there we go.

6:11It finishes.

6:12So also, did you notice the starting timeout didn't actually begin until two

6:17seconds in,

6:18whereas the old way when it was just a promise, you know, when two second delay

6:22was just a

6:22promise, that was printed out to the console immediately when we started

6:27running the program.

6:29So let's make this a little bit more interesting here.

6:31What we're going to do is we're actually going to maybe change this function

6:35here to something

6:37like, we'll call it something like create delay.

6:42And what we're going to do is we're actually going to allow ourselves to pass

6:46in the number

6:47of milliseconds that we want the delay to be.

6:49All right.

6:50So this is making this delay thing a little bit more, a little bit more

6:54flexible, because

6:55what we can do now is if we want to introduce a delay, right, we can say

6:59something like create

7:01delay.

7:03And then maybe we'll wait for one second.

7:06And we can say dot then, and then we can say something like console dot log, we

7:12'll say,

7:14one second has passed.

7:17And then we can actually return another delay.

7:19We can say return create delay.

7:22And we can maybe create a two second delay.

7:25So we'll say here, we'll just copy this dot then thing, because I want to do a

7:28few of

7:29these, we'll say, maybe a total of three seconds have passed.

7:33So we'll say three seconds have passed.

7:38And then down here, we'll, we'll do one last delay.

7:41We'll do three seconds.

7:42And that would be a total of six seconds.

7:45So we'll say six seconds have passed.

7:49All right.

7:50And then we'll just not insert an extra delay there.

7:54And that should be all we need to do.

7:56So if we run this code now, what we're going to see is that these console dot

8:00log messages

8:01will be logged out after specific amounts of time, right, at specific intervals

8:07.

8:07And if we do that, here's what this is going to look like.

8:10All right, we see one second is passed, three seconds have passed, and then the

8:15last one

8:15here, six seconds have passed.

8:19And let's also go in here and actually delete the starting timeout and timeout

8:22finished things.

8:24And that'll give us more simplified version of our promise.

8:27And actually, we can simplify this even more by just having resolve itself be

8:33the callback

8:34for set timeout.

8:35All right.

8:36So that's just about the simplest version that we can have of that promise.

8:40All right.

8:41So anyway, that is the basics of using promises to insert a delay.

8:45And we also learned about how to make sure that we had control over when a

8:50promise started

8:51by having that promise get returned from a function instead of just assigned to

8:57a variable.

8:58And just another thing to note is that we also saw we've already seen this a

9:02few times,

9:03but I just want to tie this back in.

9:05We've also seen that functions like read file or FS dot on link, those actually

9:12return promises.

9:13So in other words, those are pretty much the same thing as this one here.

9:16Since the difference with our create delay function is that the asynchronous

9:21operation

9:22that it's performing is just waiting a certain number of milliseconds.

9:26All right.

9:27So anyway, I hope this has been informative for you and I'd like to thank you

9:30for viewing.

9:30[BLANK_AUDIO]

Challenge & Solution: Promisifying Callback Functions

0:00All right, so now that we've seen the basics of using this new promise

0:04constructor and

0:05plenty of other details around how to use it to maximum effect, it's time for

0:10you to

0:11apply what you've learned here by doing a challenge.

0:14Now, the challenge here is going to be a pretty interesting one because I

0:18guarantee you will

0:19find it useful in your JavaScript code whenever you're using some sort of some

0:25sort of library

0:27or something like that that doesn't natively support promises that can happen

0:31quite often

0:31where for one reason or another library that you need really only works with

0:36callbacks.

0:37Well, the good news here is that in general, it's always possible to convert a

0:42callback

0:43into a promise.

0:45And as you may have guessed by now, that is going to be your challenge.

0:48So your challenge here, let me just create a new file here, which I'll call

0:52something

0:52like promiseify challenge.

0:58There we go.js.

1:00Your challenge here is going to be to promiseify certain functions in the FS

1:06package without using

1:07the dot promises property that's cheating.

1:11You can't do that.

1:12So in other words, what you're going to do is you're going to use the same

1:15method that

1:16we just saw with using set timeout to implement a promise delay in order to

1:24promiseify, you

1:26can really choose what functions you want, but I'm going to be doing read file

1:30and on

1:30link.

1:31All right, and that should allow you to do things like say FS dot read file.

1:38And then you can obviously put in the details there and say dot then.

1:41All right, now you are going to need to create sort of a wrapper here, such as

1:45you might

1:45say something like function read file and actually create that promise inside

1:52of here.

1:53So that would look more like this.

1:55But you get the idea, right?

1:56You're going to need to create a promiseified version of FS dot read file and

2:02FS dot unlink

2:03and a further part to your challenge.

2:06If you dare go here is to create a generic promiseify function.

2:11All right, so it might look something like this promiseify that takes any

2:16function that

2:17returns a callback and returns a promiseified version of that function that can

2:23be used with

2:24the dot then syntax.

2:26Right.

2:27So this might look something like this if you have function promiseify and FN

2:30and to make

2:30it easier for you, you can also pass in maybe the number of the argument or the

2:36index of

2:36the argument where that callback is usually found just so that you'll be able

2:41to work

2:42with different functions that have that callback function in different places,

2:46right?

2:46So maybe we'll call that something like callback index.

2:50All right, so that is the second part of your challenge.

2:53If you can't figure that one out, don't worry too much, but you should be able

2:56to figure

2:56out the first part of it.

2:58So give this challenge maybe five to 10 minutes.

3:01And once you've given it a try, feel free to move on to the next video where I

3:04'll walk

3:04you through how I solved this challenge.

3:07So I hope this has been informative for you and I'd like to thank you for

3:09viewing.

3:10[ … ]

Challenge & Solution: Promisifying Callback Functions

0:00All right, so hopefully you've given this challenge a try.

0:02What I'm going to do in this video is walk you through how I solve this

0:05challenge.

0:05So to get started here, let's take a look at how to create a promise version of

0:11the

0:12FS packages functions.

0:14We'll start off with read file.

0:16And what this is going to look like is we'll just say function, I'll call it

0:19read file,

0:20and this is just going to take the file path and the encoding and pass those

0:26along.

0:27Now, if we want to be able to say something like read file dot then and have

0:33the results

0:34of the file printed out, right, in that case, it would be the actual file

0:39contents there,

0:40what we would need to do is, well, the first thing that we know that we need to

0:43do anyway

0:44is have this read file function return a promise, right?

0:49That's the only reason that we're able to, oh, and here I actually did that

0:51wrong.

0:52This should be something like file one dot txt.

0:56And by the way, I'm just going to be using the file one dot txt thing here as

0:59an example

1:00with a bunch of lorem ip some in it.

1:03And then of course you could say, oops, let's try that again, you could say utf

1:08eight in

1:09there, right?

1:10If you want to be able to do this and add dot then, you know that this file is

1:14going

1:14to need to return or this function rather is going to need to return a promise.

1:19So just knowing that we at least know how to start, we can just say return new

1:25promise.

1:26All right.

1:28And then the next thing that we're going to want to do is obviously we're going

1:32to want

1:32to load the file based on the file path and encoding arguments that were passed

1:38in.

1:39Now what function do we know that is going to allow us to load files?

1:44Well, obviously the fs dot read file function.

1:47So what this is going to look like is we're going to say resolve and reject as

1:52the first

1:53two arguments here.

1:55And then we're actually just going to use the regular old callback based fs dot

2:00read

2:00file function in order to load the file.

2:03And here's where it's all going to tie together.

2:06What we're going to do is we're going to say fs dot read file file path and

2:11encoding.

2:12Let me actually spell that right there encoding and the last thing we're going

2:17to do is we

2:18are going to pass a callback here that has the regular old error and contents

2:25arguments.

2:26But what we're going to do is instead of actually doing anything with those

2:29arguments, we're

2:30going to just pass those along to either resolve or reject.

2:35So here's what this is going to look like.

2:36We're going to say if error, right, if an error occurred, then obviously

2:40something went

2:41wrong and we should reject the promise, right?

2:44So we're going to say reject and we're just going to pass that error along like

2:49so.

2:49And we're actually going to say return so that that will sort of short circuit

2:53that

2:53callback function.

2:55Now on the other hand, if everything went well, right, if the contents of the

2:59file were

2:59successfully loaded, then we can just call resolve with those contents.

3:05And that is all that we need to do, right?

3:07That will allow us to use this read file function in this way with really any

3:12file we want.

3:14So let's give this thing a try what we're going to do.

3:16Actually, we already have the code written out here, but let's actually add a

3:21catch block

3:22there because I do want to simulate an error at some point just to make sure

3:25that that

3:26part works as well.

3:27We're going to say console.error error error.

3:30And if we run our code now, what we're going to do, all right, oops, let's try

3:34that again,

3:35we'll say node, promiseify challenge.js.

3:38Sure enough, we'll see all of the contents of the file logged out to the

3:44console, right?

3:46And that is again, coming from our dot then callback, right?

3:50It's not coming from the original FS.read file function.

3:54I mean, not directly anyway, we've successfully converted this read file thing

3:58so that it's

3:59almost indistinguishable from FS.read file from the FS.promises portion, all

4:06right?

4:07So let's check out what happens if we have an error.

4:10Let's just misspell the file name here.

4:12And if we run our code here, sure enough, we'll see that it rejects our promise

4:19and we

4:19get the error logged out to the console.

4:21Cool.

4:22So that is the read file function.

4:25The other function that I told you to do was the unlink function.

4:28So I'm going to do the same thing here.

4:30We're just going to say unlink and that's going to take the file path that we

4:33want to

4:34delete.

4:35And same thing is going to go for this one, right?

4:37If we want to be able to say unlink dot then, we need to return a promise in

4:42here just for,

4:44just to give you a little visual here, I'll say unlink.

4:46And we'll, let's let's actually delete a file that we don't need as much.

4:49We'll delete file for here.

4:50We'll say unlink file for dot txt.

4:54That's all we need there, but what we want to be able to do is say dot then,

4:59and obviously

5:00have some callback in there and dot catch and have some callback there.

5:05Now, once again, in order to do this, we need this unlink function to return a

5:10promise.

5:11So here's what that's going to look like.

5:12We're going to say return new promise.

5:16And we're going to just have resolve and reject same old arguments as before.

5:20And the next thing that we're going to do is we're going to say f s dot unlink,

5:24just

5:24use that classic callback based unlink function, or the callback based version

5:30of that function

5:31anyway.

5:32And we're just going to pass the file path along to it as well as a callback.

5:36And that callback's just going to take an error in this case, because there's

5:40not really

5:40any result that we want to subscribe to.

5:44So in this case, we just have to say if there's an error, we're going to reject

5:49with that

5:50error.

5:51Otherwise, we're going to resolve.

5:53And since there's no result that we want to pass along, we're not going to pass

5:56any

5:57arguments to that.

5:58Cool.

5:59So let's try this thing out.

6:01Let's just add a dot then callback there.

6:04We'll say dot then and then we'll say something like console dot log deleted

6:10file successfully.

6:11Oops, I misspelled successfully there.

6:14Let's add another s.

6:15There we go.

6:16And for catch, what we're going to do is we're going to say error.

6:20And what we'll do is of course, we'll log out the error with console dot error.

6:26There we go.

6:28And then we'll say something like console dot log and we'll just log out

6:33something like

6:34unable to delete file.

6:38And oops, it looks like I had a spare semicolon there.

6:41So let's remove that.

6:42And now we should be able to run our code and the read file function is going

6:47to run

6:48as well as the unlink function.

6:50So let's just give this a try.

6:52We're going to run node promisify challenge dot JS.

6:55And sure enough, we see that it deleted the file successfully.

6:57At least that's what it says.

6:59And if we go in here, sure enough, we see that file for is no longer there.

7:03All right.

7:04And well, that is the solution to the first part of the challenge.

7:07The second part of the challenge was pretty interesting.

7:11And really what I was kind of hoping would happen for you was by seeing these

7:16two promisified

7:17functions that you created side by side, you'd notice that there's really very

7:22little

7:22that's different about those functions.

7:25And you could maybe create a more generic version of those.

7:30So basically what I did for this is I just took, I just took the read file

7:35function.

7:36And what I did is I pasted that inside here.

7:40All right, that gave me a good start for creating a generic promisify function.

7:47And in this case, what we would want to do is not return a promise immediately.

7:51We'd want to return a promisified version of this function.

7:55So what this would look like is we would say return function.

7:59And this would take some undetermined number of arguments there.

8:04And basically this function inside of here would be the one that returns the

8:10promise,

8:11right?

8:12In other words, look at what we had to do when we converted FS dot read file,

8:16we had

8:16to actually create another function that returned a promise.

8:20So in order to generically promiseify any function, we can just return a

8:25function that

8:26returns a promise.

8:27All right.

8:28Now, the tricky bit here is actually getting that actually tapping into the

8:33callback there

8:34because what we have to do is we have to say something like const callback.

8:39And this is just going to represent the generic node JS callback with error and

8:43result.

8:45All right.

8:46And what we're going to do with this is we're just going to have this callback

8:51function do

8:52essentially exactly what we did in here.

8:54So in fact, we can just take these two lines and put them inside callback right

8:58there.

8:59All right.

9:00And now we just have to make sure that this callback function gets to the right

9:04place

9:04in the arguments that we're passing through to whatever function we're

9:08promising.

9:09So what that's going to look like is this, we're just going to say instead of

9:12FS dot read

9:13file, we're going to say FN, whatever function it is, we're promising there, we

9:18're going

9:18to pass all of the arguments to it except for the last one.

9:24And I allowed you to add this CB index in there because that just made it a

9:28little bit

9:28easier.

9:30So what we would have done there is we would have said something like const new

9:35args equals

9:36args.

9:38And then what I did is I just said new args index callback index equals

9:44callback.

9:46All right.

9:48So now all we have to do is pass those new args to our function.

9:52Like so we're just going to say dot dot dot new args, which will pass all of

9:57those as arguments

9:59to our function.

10:00And we're just going to say, actually, we don't even need to say return there

10:03because

10:03any value will get passed through to either resolve or reject.

10:07Oh, and sorry, this should be a result here instead of contents.

10:12So that should be all that we need to do there.

10:14Oh, except for one other important thing, this callback actually needs to be

10:18inside

10:18this executor function so that it has access to resolve and reject.

10:24So let's just make that change there.

10:25And that should be all we need to do.

10:27So let's just try this promiseify function out.

10:30And to do this, I'm just going to move it.

10:33Actually, I don't need to move it anywhere.

10:35I'm just going to comment out our read file and unlink functions.

10:39And we'll replace those with promiseify called on FS dot read file and on FS

10:46dot on link.

10:47So here's what that's going to look like.

10:48We'll say read file equals promiseify.

10:51We're going to call that on FS dot read file.

10:56And then we'll say const on link equals promiseify.

11:02And we're going to call that on FS dot on link.

11:05And that should be all that we need to do.

11:07So if we run our code again, actually here, let's try deleting file three now.

11:13If we run our code again, we should see that both these things work in just the

11:17same way,

11:18but we now have this tremendously powerful promiseify function that will allow

11:22us to

11:23promiseify any function that doesn't that that doesn't natively support

11:28promises.

11:29So here's what this is going to look like.

11:31We're just going to run our code again.

11:33And oops, one thing I forgot is we need to actually specify the callback index

11:37in these

11:37cases.

11:38So that's going to be index two for read file and index one for unlink.

11:43So let's try that again.

11:45And sure enough, we should see that it deleted the file successfully.

11:48And lo and behold, that file is no longer there.

11:51Now again, I think I mentioned already, but if you wanted to make the

11:54assumption that

11:55the callback was always going to be the last argument, which is true in most

12:00cases in no

12:02JS, you could save yourself having to pass in that extra CB index argument

12:07there.

12:07But I'll leave that up to you as an exercise.

12:10So I hope this has been informative for you.

12:12And I'd like to thank you for viewing.

12:13[BLANK_AUDIO]

Team training path

Turn this skill into assignable team training

This free skill is a preview of the courses your team can assign, track, and report on with CBT Nuggets.

What's next?

Ready to keep going?

For your team

Bring this training to your team

See how CBT Nuggets helps IT teams close skills gaps, hit compliance targets, and prove training ROI.

Request a Demo

Just need JSNAD? Enroll from $300/yr (42 skills)

Request a Demo