Kyle Simpson: Now lets talk about promises, okay. I know we're running late, if you have to leave it's okay, I understand. I'm trying to get through it quickly, but this is the stuff I'm actually most excited about, so I hope this is an interesting team. Promises. Promises there's a lot of different ways that people explain ' there's a whole bunch of great blog posts about promises, I encourage you to kind of take a look at some of those.
Let me just give you two metaphors for what a promise is all about. Okay, the first one, is you walk up to the counter at Burger King or McDonald's or something like that, and you're hungry for a Big Mac or a burger whatever. And you hand the cashier, you order your food and you hand the cashier some money, what usually happens is you don't have your food back right away, what does the cashier hand you instead of your food.
Speaker 1: Receipt.
Kyle Simpson: A receipt, and that receipt has an order number on it. So you step back among the other masses of people that are impatiently waiting for their high caloric intake food. And you wait patiently, unpatiently for somebody to call out that order number, that magic number on your receipt.
And then what do you do once they call out your order number? You walk back up to the counter and you exchange your receipt for the food that you actually wanted.
Kyle Simpson: So what we have here is we have a transaction that was asynchronously completing. I started the transaction by giving you some money, but you couldn't complete the transaction and give me my food yet.
You had to give me a promise for some food. You had to give me an IOU for some food. And you had to come back at a later time and exchange my order number for my food, okay? That, metaphorically, is exactly what promises are. I call to a function, and I want some end result to happen.
And that function tells me, sorry I can't finish it yet. But I'll hand you back a promise, I'll hand you back a receipt with an order number on it. And at some later time when I get finished with that task, I'll let you exchange the order number for the value that you asked for.
Does that make sense? All right. The other metaphor that I would give you for promises, is what if we could call a function and we weren't sure when that function was going to finish. But what if we could subscribe to an event after calling the function, we had some mechanism by which we could subscribe to an event that lets us know when that function finishes.
We might call that a completion event or a continuation event. kind of like we listen for click events on buttons, but this is an event for a function call. That's essentially what promises are. We're calling a function, it doesnt finish yet, but it allows us to subscribe to a continuation event.
And when we get notified of that event, then we proceed. Does that make sense at all? Let's see what that looks like in code. I'm going to use, this is very heretical in the broader standards community, because everybody seems to, in the standards community, they seem to universally hate the jQuery implementation of promises.
Because jQuery had the gall to implement promises in a non-standard way. And jQuery can't go back and change it now because there's ten million lines of code relying upon it. So If you talked to anybody in the promises and the standards community, and you mention jQuery promises, they will scowl at you and say you shouldn't be using those.
I think that's hogwash, that's nonsense. jQuery has promises, they're useful, it's a pattern rather than an API as far as I'm concerned. So I'm going to show you first how jQuery does it. We create these things called deferred and we pull a promise object off of our deferred, then we have two separate pieces of code.
Lines four through six and lines eight through ten would likely happen in two totally different places in our code, because there are some separation concerns. Lines four through six are what happens when we want to listen for the event, in this case we want to listen for the done event, the continuation event.
So we would return back a promise from some utility and that calling place would be able to listen for the event that was finishing. And then somewhere inside of our code we would at some later point we would resolve that promise. We would exchange the order number for a big mac.
So when we call resolve on the deferred, he will automatically fire the done event for any promises that are listening to him. Okay. Here's how we use it for example, creating ourselves a little delay function that I call wait for N. I create my deferred, I return my promise, I set up a time out for calling D dot resolve.
That's the typical pattern, and you'll see that with all promise implementation, that same kind of pattern. So here's how we use it, we call wait for N, 1,000., wait for N 1000 returns us back a promise. So when we call .then, we're listening for the continuation event on that returned promise.
So our code says wait for n, wait for 1000 milliseconds, then do this stuff. Inside of this this stuff function, we call wait for n again, which generates a whole new promise, and when we return a new promise from it it chains the promises together. So this code you can look at it very synchronously, it says wait for a thousand then to this, then do this, then do this, then do this, even though it stops asynchronously.
So you can see that promises give us something similar to what we saw with generators. They give us a very synchronous looking syntax for an asynchronously completing series of tasks.
Kyle Simpson: So, everybody follow that?
Kyle Simpson: And here's why it's important. Remember when we talked about inversion of control?
When I pass a callback into some utility, that utility has control over when my code happens. We've reinverted the control, we've uninverted the control now. We call some utility, and rather than giving them our continuation, that utility hands us a promise back. And we get to decide what we do with that promise.
We listen for the completion of that promise and we decide what to do next. So we've uninverted that inversion of control and brought it back so that we are now in control of the entire completion of our program. Does that make sense? That's why promises are such a powerful solution to callback hell and inversion of control, is because they uninvert that inversion of control.
Now, promises are actually built in as of VS6, so you can use them natively directly in the language. We're going to get the capital P promise. It's already there in Chrome and Node. You can play with it if you want. We construct our promise. This should look very similar to what we were doing with JQuery.
We construct a promise that we return back, and then we call a resolve at some later point. And we call .then and .then and when we return new promises, it does exactly the same thing. This is why I don't care that jQuerys API is slightly non-standard, because the concept is the same.
We still reason about the code in exactly the same way.
Speaker 2: Kyle. Is there part of that chain strategy for each one? If you say, I get a time out in this one, I want to do this? Is there like a then otherwise?
Kyle Simpson: Yeah. In native promises, if you pass two functions in, the second function is the error handler for that stage.
So there is a way to call reject if you want to fail a promise. There is always an error path.
Kyle Simpson: All right, so we get data, 1,000 milliseconds from now, it passes along this message. Promises have message passing obviously. So 1,000 milliseconds from now, num one will be ten.
A thousand milliseconds from now, num two will be thirty. And a thousand milliseconds later, the answer will be the string meaning of life forty-two.