Promises represent a placeholder for a future value. They solve the inversion of control issue that exists with callbacks by providing completion events for asynchronous tasks. This puts the control back inside the application.
(intense music) - [Kyle Simspson] What is a promise? There are a multitude of different ways, several different ways that promises are explained. And I will choose two or three of those explanations here by way of metaphor, and illustration. Again, because it's more important to me that you understand the concept behind promises first before understanding the API. It's the reverse of the way most of this stuff is typically taught. But I want you to understand why promises are so important.
Because they're not perfect. And when there's some frustration with a promise or something that's weird, or there's some gotcha, there are gotchas there. And when there's some gotcha down the road and you're frustrated and you find yourself, and here's a clue, there is such a thing as promises hell, If there's a call back hell, there's a promises hell. When you find yourself stuck in promises hell and you're cursing at them, I don't want you to turn around and say well I can just get rid of promises. You need to understand why they're more important than just the usage of your API.
If I could change it, there are some things I would change about the API. But I wouldn't change the fact that they are there. They are one of the most important advances that we've made in codifying reasonable asynchronist coding patterns. So, first let me give you a scenario around promises. It's silly, it's early here together and I want to make sure that we're all kind of awake. I see people sipping on coffee so have more coffe because your brains are going to have to fire on all cylinders to get stuff today.
So here's a silly metaphor to explain to you. I walk up to the counter at my favorite fast food restaurant and I order a cheeseburger. So I ask the lady, I'd like a cheeseburger and she says that'll be $1.39. So I had her the money, give her the $1.39, so I have begun a transaction by ordering and giving some money for something. What am I expecting in return of this transaction? I'm expecting a cheeseburger. But often times I'm not handed a cheeseburger immediately. What instead am I given? A receipt.
And importantly on that receipt it has an order number on it right? My order says order number 317. So I take that receipt and I look at my order number and that order number has become a place holder for my future cheeseburger. It is an IOU, it is a promise for a future cheeseburger. They owe me a cheeseburger because I have given them money. I have started a transaction. Now I don't have the cheeseburger yet. I can't bite into it. But that doesn't mean I can't begin to think about and reason about, and dream about my future cheeseburger.
I can begin to think about it, and my mouth can begin to salivate, and I can begin to have cheeseburgers dancing in my head about how amazing this cheeseburger is going to be. I'm famished, I can't wait to eat it. I have something in my hand that allows me to begin to reason about this cheeseburger even though I don't yet have it. And then that magical, those magical words; order 317. And I walk back up to the counter, receipt in hand. Order 317 printed on it. And I hand her my receipt and what do I now get in return? I not am exchanging that promise for the value for the value itself.
This is a silly metaphor, but a metaphor none the less, for what is happening with promises. Promises are a notification of the idea that we need a placeholder to eliminate time as the concern wrapped around the value. We need a container around it. In programming speak we call that a future value. It's a value that will eventually, at some unspecified point become fulfilled, but in the meantime we still need to be able to reason about it exactly the same way.
Because we don't want to sit around waiting, wondering and having all these forks of different logic. That's the complexity that makes our code hard to understand, hard to maintain, hard to be bug free. So the promise becomes a container that wraps around a value. In fact promises come to us primarily by way, they're not original to Java Script, but they come to us primarily by way of a language called E. One of the members of the TC39 committee, Mark Miller is the creator of the E programming language.
And in E they have these things called futures. And in E a future is literally replaced by it's value. It's literally exchanged by it's value. But you can perform the operations that you would normally do against that value directly, transparently. Even though the value isn't physically there yet, you can begin to compose it. You can begin to perform operations on it. We didn't get quite the same thing, but he said you know what, this is really powerful in E.
We should bring something to Java Script that allows people to reason about values, ignorant of the timing. Values are the important thing and composing values is the important thing. If it sounds like it's kind of related to functional programming, it's because it is. Not to throw back in those terms, but promises, not their API, but their mechanism they're basically a monad. They're functional programming concept. The API is not quite as clean as a functional programmer would like, and there have been experiments to create other versions that are more functionally sound.
But the principles are basically the same. So if it sounds functional, it's because it is. So that's one way of thinking about a promise. Is that it's a future value. Another way of thinking about a promise is that it un-inverts the paradigm that we're traditionally used to interacting with some other mechanism that's going to be asynchronist in nature. When I call some utility and I know that utility is not going to finish now, it's going to finish at some later point, when I call that utility, how do I wait around to hear that.
I have to give in a call back. I have to cast the call back in. And you remember I said that's the inversion of control. When I wrap up the second half of my program in a call back and pass it to someone else, I give them the continuation control and now I've inverted the control that I had. But what if we could un-invert that paradigm. If we could un-invert, or rather not invert it in the first place. Rather than passing a call back to a utility, what if we could say something like I'm going to call some function and I know it might take awhile for it to finish.
I want you to return to me, when I call the utility, I want you to give me back something. I want you to give me an event listener. An event listener that I can subscribe to a completion event. So I'll listen for the completion event and you just fire that event whenever you're good and ready, and I'll be notified through this event listener that you've finished your work and I'll know it's time to move on. In fact, in addition to being a completion event I could also listen to an error event. If you had some error to notify me, or other things that you wanted to notify me about, I could simply receiving that listener back from you, and I know that's a tried and true pattern to receive something and listen to it.
Listen, subscribe to events.
Note: This course was created by Frontend Masters. It was originally released on 3/29/2016. We're pleased to host this training in our library.
- Parallel and asynchronous code
- Working with callbacks
- Using thunks
- Exploring promise flow control
- Abstractions, sequences, and gates
- Observables, events, and sequences
- Blocking channels