Rethinking Asynchronous JavaScript

Exercise 3 Questions Part 2

Kyle Simpson

Kyle Simpson

You Don't Know JS
Rethinking Asynchronous JavaScript

Check out a free preview of the full Rethinking Asynchronous JavaScript course

The "Exercise 3 Questions Part 2" Lesson is part of the full, Rethinking Asynchronous JavaScript course featured in this preview video. Here's what you'd learn in this lesson:

Kyle continues answering audience questions about exercise 3 before moving on to the next exercise.


Transcript from the "Exercise 3 Questions Part 2" Lesson

>> [MUSIC]

>> Kyle Simpson: Describing this with the func term, right? So the Promise is a function that has a value that then I can access on my-
>> Speaker 2: Do you really mean this, capital P promise?
>> Kyle Simpson: I think so. Okay, capital P, Promise is built into Java Script. It is a constructor that has to be called with the new keyword so that makes it very different from anything we were talking about with funcs.

The way you construct a Promise is to pass in a function which I've called executor here. That's the terminology used in the spec. Whatever function you pass in and whatever it's called is going to receive to function callbacks. Two utilities that you can use to handle the resolution of your Promise resolved for fulfilling reject for rejecting.

>> Speaker 3: And so, I'm just want to take this connected to the flow, cuz at some point when I call, I pass at output, right? My promise has been returned, right? It's when it finishes its work it will then know that I've registered output to it, right? And then you'd send, say, okay, now I'm going to execute output because you registered.

>> Kyle Simpson: I think it's-
>> Speaker 3: The function to.
>> Kyle Simpson: I think maybe I want one of the confusions I'm not sure, but I think maybe part of the confusion here is you're trying to conflate the whole process into one mental step. It's two entirely separate concerns. One concern is how the Promise gets resolved, that's what I'm showing here on the line 25, line 25 is resolving the Promise.

Don't think about how a Promise is resolved, when you switch hats to think about how you respond to a Promise resolution. You're going to get confused if you try to think about those at the same time. Line 38 is a response to a Promise resolution, and on line 38 who the hell cares how it got resolved.

Doesn't matter how it got resolved. All that matters is this is how I'm declaring the response to a Promise. I would recommend keeping those two completely separate in your mind. Cuz it seems like some of the questions are kind of conflating when people are saying is this the resolve value or whatever.

That might be were some of the confusion, is trying to keep those as one step. There are two entirely separate capabilities. And that's important, by the way. That's a separation of concern. We should be able to think about the response to a Promise entirely independently to how a Promise gets resolved.

>> Speaker 3: I just want to make sure the thing I have to tell myself is just be ignorant of whatever is happening and just do this.
>> Kyle Simpson: That is absolutely not what I want.
>> Speaker 3: That's what I wanna avoid and so that's why I'm asking to try to understand.

>> Kyle Simpson: I absolutely that is the antithesis of everything I teach I do not want the message to be, don't understand it. I want the message to be understand it separately so here when I call resolve, I am telling the Promise that's a magical function connected to the Promise I am telling the Promise under the covers resolve yourself.

And the response that a Promise does when it is told to resolve itself is to go and look for anybody that's registered and then handler and execute that then handler and pass along its values. That's the sausage making of how a Promise implementation is built. It's got an internal array of then handlers and it loops through them.

>> Speaker 3: Yeah, that's what I was trying to articulate earlier though. The output is in that set of things that is done under the covers to.
>> Kyle Simpson: Yeah, I think maybe where I got where we were getting confused as you were saying output is result, it's not.
>> Speaker 3: No, no, no, yeah.

I said that earlier, that was-
>> Kyle Simpson: Resolve fires off an asynchronous action under the covers that tells it to go through a list of then handlers that have been registered and one of those then handlers is going to be the output function. And it will make sure to pass the message along, okay?

That's all implementation inside of a Promise. And there are Promise libraries that you could go and read that are spec compliant Promise libraries. You can go and read and see how they do those things, and I I recommend that. I wrote Promise libraries as part of my understanding of promises.

>> Speaker 4: Are you gonna get to catching errors? There's some questions that-
>> Kyle Simpson: I don't really think we're gonna pay much attention to catching errors at this particular point.
>> Speaker 4: One of the questions was just, if you would put a catch at the end, would that catch errors in any of the at ends?

>> Kyle Simpson: Yes, catch is a shorthand, okay? If I do a catch here. It would receive an error message anywhere in this chain that created an error. Even if I did something, I should have taken this out a long time ago, anything in this chain like if I call a doesn't exist function.

That's gonna throw a JavaScript error because there is no doesn't exist function. That JavaScript error is going to turn into of a rejection of the promise that was returned to line 43. Because line 43 doesn't handle it and line 44 doesn't handle it and line 47 doesn't handle it and line 48 doesn't handle it.

That rejection is going to propagate its way all the way down the chain skipping all those other steps and it will finally be caught here on line 51. And we'd get the JavaScript exception printed here. The .catch is the same thing as a .then where we don't pass anything for the success handler.

So those two are functionally equivalent. Where and how often you register error handlers is there is no hard and fast rule for this it's dependent upon the behavior the intended behavior of your system. If I register to catch right here for example, then what happens is once a error has been caught.

It's exactly synonymous to a try catch, which means that it was caught and it allows the rest of the chain to continue as normal. So if you want to recover from an error at some point in your Promise chain, you can put an error handling there. If on the other hand your assumption is that an error anywhere in the chain is a fatal unrecoverable condition and we need to fall out of everything, then just put a catch at the end of your chain or a mixture they're of.

But there's no hard and fast rule to answer that just you have to figure out. It's exactly the same as me telling you to wrap a try catch around your whole function. Or do you warp a try catch around every single line of your function? The answer to that question is up to you.

And up to how you want to handle it.
>> Speaker 3: And the input to line 40 the value would be the return value from the catch. Right, catch is gonna return a value and that will then be the value passed to 40.
>> Kyle Simpson: Your error handler can return value that becomes the success for the next step.

The reason I didn't want to get into error handling is because we get into a whole side rabbit trail of complex issues. Those are things you'll discover as you play more with Promises but I don't want us get too far off track and understanding the overall pattern here.

So you're gonna need to practice with promises I have written about all of this stuff in detail. I encourage you to go and read the books and blogs that I've written about. These Promise issues and I do cover error handling in exquisite detail.
>> Kyle Simpson: All right, let's pop the stack back to where we were before, just to make sure we're back on the same track, p1 .then(output) .then return p2.

.then(output) .then return p3. .then(output) then output complete. That's the canonical flow control here. Did we get the questions handled?
>> Speaker 4: I think so, it sounds like it. I think the biggest thing was that they didn't understand what the promise API what that actually looked like and that was where the resolve was actually coming from.

>> Kyle Simpson: Okay, this solution is nice, it has an elegance to it. It's a vertically oriented chain instead of a nesting, I mentioned to you that there is such a thing as Promise hell. And one of the expressions of Promise hell that you should be aware of, it's kind of what I was getting at earlier about not conflating concerns.

Another way of thinking about this Promise chain is to say something like I'm going to call the output function for text. And then I'm going to call p2.then
>> Kyle Simpson: And inside of that function I'm going to output the text and then p3.then.
>> Kyle Simpson: And I'm going to output the text and output complete.

Without me putting in the extra curly brace and closing parentheses, that's a completely valid way of expressing the flow control, it will have the exact same end result. This is a bad style, this is a bad idiom, and this is one of the expressions when people talk about Promise hell.

If you find yourself back to the whole nesting thing, you're missing the point. And the real point that you're missing here is your return a Promise to get yourself back to the original chain. Instead of chaining off for the Promise here return the Promise back to the main chain and do your you're chaining vertically, okay?

So be careful about that. It's very easy to fall back into that same temptation is what we've always done which is I'm used to nesting things together. This is one of the ways you get yourself back into what we call Promise hell.

Learn Straight from the Experts Who Shape the Modern Web

  • In-depth Courses
  • Industry Leading Experts
  • Learning Paths
  • Live Interactive Workshops
Get Unlimited Access Now