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

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

Using the checkout example, Kyle introduces the native Promise API. He also explains that even though promises appear to use callbacks, there is a increased level of trust. Promises will only resolve once, will have either a success or error outcome, and are immutable once resolved.


Transcript from the "Promise API" Lesson

>> [MUSIC]

>> Kyle: So, back to our track checkout if you recall from before, that silly scenario about the eCommerce. And rather than passing my callback in, what if we were to modify that API such that it returns back an event listener to us? As you see on line 11 I listen to, I receive a listener back from the track check out function and then on line 13.

I listen to the completion event and when it finishes I move on. And I listen to the error event and when it finishes I move on. Can you see how that is an inverted the inversion of control or rather just simply retain control? Because now rather than passing my call back into that utility, giving them the keys to the kingdom by which they can do whatever they want and I can't trust that they won't do what I don't expect.

I've retained control. I've simply said no you just give me an event listener, I'll figure out what to do. Well I'll listen for that event and we could wire it such that we listen for the event and then unsubscribe to the event the first time it happens for example, like we are in complete control of that paradigm.

So, we've normalized, we've brought more sanity back to this process, rather than passing the call back in. That's an important understanding of promises, is that they uninvert the inversion of control problem. That's a big deal. That's not a small point, that's one of the most important points. Promises were designed to un-invert that inversion of control.

Rather, to retain that control, so that all of those trust issues that we were talking about before have an ordered and patterned way of being solved. Now, we don't actually listen this way. This isn't how most APIs design, no. Although, it's an established pattern that we can at least understand, but it's It's a metaphor for thinking about a promise.

A promise is like an event listener. But rather than there being a completion event, we call that event the then event. And that's where we start to talk about the API of a promise. So, in that truck checkout utility. Rather than receiving a callback as a parameter we can simply create a promise as you see on line two on constructing a promise instance.

The constructor for the promise received two methods the resolve and the reject. It's pretty clear what those do by the way I named them. You call resolve if you wanna resolve the promise if you want to fill it completely or correctly and you call reject if you need to reject the promise.

Back to my future cheeseburger this is the only two options. Either I'm eventually gonna get my cheeseburger or, the lady is going to call me back up to the counter and say this is a tragedy but we are completely out of cheeseburgers, I'm gonna have to give you your money back.

This is the only two options, right? Either I get my cheeseburger or get my money back. So, we can either fulfill the promise calling resolve or we can reject it. Those are the only two outcomes that a promise can have. So, whatever that magic is I'm alighting that information because that isn't the important part but whatever that logic is inside of track check out and even if it's a call resolve or reject.

Now, you notice that we're returning that promise instance, so when we return that promise instance we're going to use it in our code. Just like I'm doing here on line 11 I receive a promise back and the notice our line 13 instead of saying dot on completion. I'm saying dot then I'm registering for then event

>> Kyle: The then event is gonna be called when either resolve or reject is fired against that promise. It will fire then event if you will metaphorically and one of those two functions passed into it's gonna get called. Finish will be called if the promise was fulfilled successfully error if it was rejected.

So, we have actually a nice clean mechanism for being notified that it was either a success or that it was a failure. It's incredibly important, step forward for an inversion of inversion of control. Inversion of control is sometimes used in an intentional way. Framework design author sometimes will use in fact, inversion of control is one of the key characteristics that has classically been used to define something as a framework as when it inverts control when you pass in stuff in it calls for you instead of you calling things.

I don't know how many of you are familiar with some of those more classical thinkings about software design but that's one of the characteristics that divides between a library a framework is that inversion of control. So, some people will tell you that inversion of control is an intentional design feature and I would tell you as far as asynchronicity is concerned it's a terrible idea.

Inversion of control is the path to the dark side here it is the path by which we completely lose all reasonability in our program. So, we are trying intentionally actively on purpose to uninvert that paradigm to bring it back into our control. That's what promises are doing for us.

So, this isn't actually about an API at all. This isn't about lack of indentation. In fact if you pay close attention, you notice there's still a ton of callbacks here. In fact there's more callbacks here than they were before. Wait a minute, hold up. I thought promises were all about solving callback error, getting rid of callbacks how on earth are they fixing anything if there's still callbacks involved?

Really important question. If there's still callbacks involved how does this promise system offer any solutions to us? You might ask and rightly so. But wait, if I passed my callback into that promise, can't the promise just call my callback a bunch of times? How can I trust the promise to do what it's supposed to do?

That's the most important question that can be asked at this point. Because you need to understand that promises were designed to instill trust into this transaction. The fundamental design principle that they're only resolved once, they can only be resolved as a success, or an error the messages that get passed to a promise are always kept.

It becomes immutable, exceptions are always caught and turned into errors that are always observable there's nothing swallowed. If you choose not to observe because you're lazy or you make a mistake, then it might look like it was swallowed but it definitely was not swallowed in the sense that you had no opportunity to observe them.

This is a huge deal. This is a whole bunch of sanity brought back to a process that has fundamentally been rather hard to understand and rather hard to maintain for the entirety of JavaScript history. So, here and we do start to see some of the benefits of the API.

These are things above and beyond this notion of time independent state. I said that was important, that's our foundation. Built upon that, we have all of this trust added to it. And that is primarily the mechanism in the API that we've been given, is designed to organize our callbacks in that certain way.

In fact, a third way of thinking about what a promise is, is that it's a callback manager. It's a pattern for managing our callbacks in a trustable fashion.
>> Kyle: That's a big deal. That's why promises matter, it's not really so much about whether you like the shiny API or not.

It's not really about whether you wanna get rid of nesting or indentation. There is a promise hell and it's easy to get into or no silver bullet. But there's a really important thing that they've been designed to do that is to instill trust back into our systems. Even more than just trust in this way.

Now that my value is immutable I mark that one on purpose because now mind that my value is immutable from the outside it cannot be changed. That means I can send that container to any port of my system or even outside of my system to other third parties and I can say, here is my value and I do not have to worry that they're gonna change that value out from underneath me.

Remember we talked about immutability in the other workshop and how important that is. That's one of these fundamental import. In fact, one of the most important things is that there are externally immutable. There's no action at a distance concern here. If you don't know that phrase, action at a distance, that's one of the evils of software architecture when you design a system, where somebody else far away can do something that affects you without you knowing him.

It's a bad idea. Just as a little side note here. There are discussions happening around promises that in a future version of JavaScript, we can make it this notion of a cancellable promise. I'm not gonna go into all the politics and all the craziness that's around cancelable promises.

Just briefly to state to you, it's kind of a tail wagging the dog as far as I see it. They have this other sort of thing that they want to control and that thing that they want to control only exposes promises. And so, let's make promises cancelable so that we can control that thing.

Instead of making that thing controllable. It's crazy to me but you know what's bad about cancellable little promises? Action at a distance. I have a promise that's not yet resolved. I pass it to somebody else and they can cancel it out from underneath me. What? That's nonsense. That erodes the entire foundation upon which these things are built.

So, if you see me ranting about cancellable promises this is why. I take it seriously because this is an important thing. We shouldn't throw it away just because we're drunk on this idea of pretty APIs.

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