 How many of you have ever written code that you don't understand why it's broken? Anyone? I figured a fair amount of you. Here's the worst question. How many of you have written code that works and you don't know why it works? Yeah. Not understanding your own code. It's a problem. And that's a perfect theme to intro into my talk today, which is called Sinking Async. We're going to jump into a deep discussion of various asynchronous patterns. And async is one of those areas that's easily the most confusing in our code. So I thought I would also point out that there's kind of a controversy over the way to spell the word sync and syncing async. So those of you that feel very strongly that it needs an H, here's that slide that'll help you feel better. And you find to pronounce the talk cinching a cinch if that helps you. But we're going to talk about syncing async. So a couple of things to, oh, I don't know why it's jumping ahead on me. Okay, so a couple of things to know about me. My name's Kyle Simpson. I'm known as Gadify Online. I'm an open web evangelist based in Austin, Texas, although I basically visit there these days because I'm constantly on the road. I speak at conferences. I teach workshops. I write books about JavaScript and I write code in the open source. As a matter of fact, I did a workshop the last couple of days here for constant contact. So as a slight little plug, if you're at all interested in getting JavaScript training, please let me know because I'd be happy to do that. So a couple of quick little bits about me. This is, I do not know why my, okay, this is my current GitHub profile. This is my current streak as of today. And it's not just a show off. It's actually, I'm using that as a tool to try to inspire people to participate in the open source community on a regular basis. So I've committed myself to doing at least one thing in the public open community per day. And sometimes it's been really difficult. It's like 11.59 p.m. and I'm like, crap, I better like file an issue against myself so that I am keeping up with my own commitment. But I hopefully that will inspire you. I'm obviously aiming towards going past a year. So I'm on the way. Also as I mentioned, I write books. I've been writing a series of books called You Don't Know JS. And we've just, I've just finished the draft of the third title. So the first two have already been published. They're available directly through O'Reilly.com, as well as all the other booksellers. And they're being written for free in the open up on GitHub. So if you go to YouDon'tKnowJS.com, it'll direct you to the repo and you can read those books. So check those things out if that's interesting. Also on that topic, I have stickers, both small and big for that series. And immediately after this talk, I'm going to go out to that first fishbowl office out there near the Esplanade and do a book signing. We've got some free books. So the first whatever 20 people that want to get in line for a book, you can get a free book and or if you want a signature on the book, I will sign it. But the most important thing that I can do to introduce who I am is to say that this is my actual uncheated score on Flappy Bird. So I'm pretty proud of that. I think that's one of the credentials that allows me to speak to you today. But in all seriousness, to get, actually there's no seriousness. I try to keep this a deep topic. So I try to keep it a little bit silly throughout the entire talk or at least attempt to. So we're going to start by looking at this long distance runner who's named Lell. And actually we're going to do a comparison between a pair of Lell's and a sink or rather a parallel versus async. We're going to look at these top, I know it's cheesy, right, grown worthy. We're going to look at this topic of a parallel versus async to start with parallel. I want to jump into the topic of threads and I particularly love this picture because this picture reminds me that threads are an awful lot like hanging yourself with a noose. And if you've ever written threaded programming, you'll sympathize with that probably. But threads, what are they? Well, I guess the best way that I can describe what a thread is going to be is kind of like at an amusement park. It would be really silly if only one person could ride the ride at any given time. We load up a whole bunch of people onto the ride and everybody gets to enjoy the ride at a time. So that's kind of my silly metaphor for what threads are, is that it's multiple actions that can literally be happening at exactly the same time. And a lot of people think that parallel is the same thing as asynchronous and they're actually not. So my metaphor for you on what asynchronous is, it comes from the idea that JavaScript itself as well as your browser, but definitely JavaScript is single threaded. So to understand the idea of single threaded, we can look at the lines outside of an Apple store anytime they're about to release a new product. And in particular, I love this one because apparently the entire store stopped for one customer. So apparently only one customer can be handled at any given time. And my favorite part of this picture is this guy right here who could not care less that this dude just, he's probably rocking an Android phone. He could not care less he's going to photo bomb it no matter what. But in single threaded model, only one thing can be happening at any given time. Let me give you a slightly different way of talking about it. What we say in JavaScript is that we have event loop concurrency. So here's the sort of visual way of thinking about it. The red and the blue are macro tasks and the individual numbers are micro tasks. Let me redo that animation so you can see. Basically the idea here is that they're going to interleave themselves. At any given time, the single thread can only do one of those things. But in a macro sense, these two things are happening in parallel. The red and the blue are happening in parallel because they're interleaving their different steps. So that's the idea that you want to have in mind. The difference between parallel and async. And async is the model that we deal with in JavaScript. So we're going to look at various asynchronous patterns and particularly we're going to look at callbacks. Because callbacks are basically continuations. But a more appropriate observation that I can make about callbacks is that they got problems. If you've ever written callback laden code, which probably most of us have, you know that it can get the job done. But there's actually specifically today we're going to talk about, there's two major problems that callbacks have. And we want to address those two major problems today in this talk. So the first of those I'll illustrate by what we often like to affectionately call callback. How many of you have ever seen code like this nested functions? Probably not with timeouts necessarily, but nested functions inside of functions. And this is basically with the callback mechanism one of the only ways for us to express the idea that something's going to happen and then after it finishes the next thing and after it finishes the next thing. This is also sometimes called the pyramid of doom because of the shape of that code. Boy, this is, there's some kind of wireless interference. I apologize. So here's the pyramid of doom as the shape of the code. So I might have to abandon my thing. If I rewrite this code using a different style of coding, it's called continuation passing style. You'll notice that there's no more obvious nesting and indentation. And I would make the observation that this code suffers every bit as much from callback hell as the previous code. Which is to say that nesting and indentation are not actually what makes it callback hell. There's something deeper, something more problematic here. And these are the two things that we're going to try to address about callbacks. So the first one that we'll look at is what we call inversion of control. And to illustrate that, let me give you a silly scenario. You've written an e-commerce page. And on your e-commerce page, you sell $10,000 TVs. And you've built the whole thing out, the whole checkout system. And on the very last page, you have to call a track checkout function, which is provided to you by some third party analytics package or something like that. You have to give them a callback to say, let us know when you finish tracking the sale so that we can go ahead and complete the sale, charge the customer's credit card, show the thank you. So you see that here in code. We're going to charge the customer's credit card and show the thank you page. You roll this code out into production and everything works great. It goes on for six months and everybody's happy. Everybody's buying the TVs. You're happy. Your boss is happy. Your customers are happy. One morning, you're casually sipping your latte at home and your boss calls you panicked, hair on fire saying, you got to get into the office right now. We've got a major crisis. So you run into the office only to find out that one of your big customers was charged five times for the same TV. So their card was charged five times for that $10,000 TV. This guy has a $50,000 card, so he's a big wig, right? So this is a big problem. You've got customer service involved. They're going to have to refund his money. But the bigger problem, even than the PR problem or the customer service problem, is the coding problem. Because now, something that you didn't perhaps even realize, a trust that you had in this code before has now been broken. There is an implicit set of trust issues with code that we write like this. And it's not just with third parties, although it's more exacerbated when we deal with third parties. And that trust is that you are trusting that when you pass your callback to them, that they will call that callback not too few times, not too many times, not losing any context, not making sure to pass along the parameters, not swallowing any errors, and a whole list of other issues that you are trusting that that code will behave correctly. And up to this point, it has been behaving correctly. In fact, you might not have even thought about these problems. But now you have a much bigger problem because neither you nor your boss are going to trust that that analytics package is going to work properly in the future. You call up their customer service and you can play and you say, hey, there's this big problem we've got. You've called our callback or something too many times. It's charged the card. What happened? They go off and they research it and they come back a couple of days later and they say, we've figured out what happened. We accidentally deployed some testing code that was never intended to be deployed. I know that's never happened to anyone. We accidentally deployed some unintentional code. We've put fixes in place. We've given you all this triage and we know exactly why and it'll never happen again. But what are the chances that you and your boss are actually going to trust that statement? What are the chances that he's going to allow you to just leave the code alone and not worry about it and just blame somebody else? Most likely you're going to have to come back and install some sort of ad hoc logic to fix this problem. For instance, in this particular case, the problem that we were dealing with is that it was called too many times. So you're going to put in some flag here that says it gets set on the first call and then it doesn't allow that code to run if you accidentally call the callback multiple times. But then you're going to be thinking to yourself, perhaps, what about all those other issues on the list? So you're going to be creating ad hoc solutions to all of those other trust issues as well. And unfortunately, most of the time when you install that sort of adhoc trust logic into this piece of code, it's not exactly the same as it needs to be in a different piece of code. So the dozen or so different places where you integrate with third party code, you're now needing to install and invent ad hoc logic for all of them. Because nobody trusts anything anymore. We've seen that this trust issue is a bigger deal than we realized. The problem is that we gave over control to some other piece of code. Now let me give you some pseudo code to illustrate a different problem with callbacks. We're going to talk about solutions, but I'm just showing you the problems. If we were to think in our minds about the ideal perfect way of dealing with asynchronous tasks, this might be one way of thinking about things sort of pseudo taskish or pseudo codeish. I could start task one, do some stuff, and then pause. And then I could start up task two. And it wouldn't matter that task one was paused because I could just go into task two, and then I could switch back and forth. And we might call this sort of cooperative multi-concurrency because we're just switching back and forth. We're choosing when to pause things. And if you were to write this sort of pseudo code, you might be able to express some fairly complex programs in a reasonable way. But when you went to put this into code that you actually could write in your program, you probably would end up writing pseudo code that's more like this, which is nested. Which you should recognize as the exact same code we already saw before. It's this nested callback thing. Because when the callback is the only way for you to express the dependency, the time dependency between steps, the only solution is some form of hard coding and nesting or continuation passing. So really the callback is just not up to the task. Let me put some more meat on that particular assertion. We can look at this particular example. And I'm showing you kind of conceptually by saying that the first half of your program is everything that's outside of our set timeout. And the second half of your program is everything that's on the inside of your timeout. What you've essentially said is I was first in control of the first half of my program, but the second half of my program I can't reason about immediately. I have to defer the reasoning about the second half to later. Which usually is OK when there's only one step, but as soon as there's two or three or five steps, or as soon as there's any complexity where it's actually the first half and then you split into thirds and things are happening in parallel, which is actually reality. We make multiple database requests at the same time. We wait for them all to come back. As soon as you get into any of that complexity, it becomes impossible to reason about your code the way your brain works. Your brain, at the highest level, I'm not talking about subconscious, like your breathing and your heartbeat and those things, but at your highest level of thinking, your brain works in a very synchronous fashion. Even if you call yourself one of those multitaskers that you can pat your head and rub your tummy at the same time, you're really not. You're just a fast context switcher. You can go back and forth between tasks really quickly. And that's actually how JavaScript works. It's this invented model that's switching back and forth between these micro tasks quickly. So our brains kind of think in terms of I'm writing the first half of my program and then I'm going to wait 1,000 milliseconds and then the second half of my program is going to happen. But in practice, JavaScript thinks I'm going to do the first half of the program. Then I'm going to do a whole bunch of other stuff. And at some point, arbitrarily later in the future, I'm going to do the second half of your program and I'll take care of it. And as soon as we introduce that model into our programming, which we have to, we've now lost the ability to reason about that second half in the same way as we reasoned about the first half. So what we're really actually going after is this idea of synchronous looking async. Or to put it a different way, we want synchronous or sequential or blocking looking code. We want the async portion of the code, which is a reality. We have to do async things. But we want the async portion of that code to essentially be an implementation detail that we hide away. We want the code that we're writing to be as close as possible to synchronous, sequential, and blocking. So that our brains will work similarly to the way the code and the JavaScript engine works. Whenever there's a disparity, that disparity grows wider and wider with callbacks. And we become less and less capable of reasoning about our code. So really, the subtitle here is that hell is callbacks. Because callbacks make it very difficult for us to understand our own code. So let's talk about some patterns that might address some of these things. The first one I'll introduce to you, again, one of my silly metaphors, is I will step up to a counter at a fast food restaurant and order a cheeseburger. And I'll hand the cashier my $1.39. And instead of getting my cheeseburger back, what do I normally get back? A receipt with an order number. So even though I wanted the cheeseburger, I can't quite get it. I've started a transaction, but I can't complete it yet. So I will take my receipt with an order number. And I'll step back among the huddled masses of other high caloric intake addicts like myself. And we're shaking, waiting for our cheeseburgers. And I hear those magical words, order 317. And a huge smile in my face comes. And I walk back up to the counter. And what do I do? I take my receipt with my order number on it. And I exchange it for that value that I was looking for, which is that cheeseburger. In essence, promises are a future value. Now, I'm not going to get into lots of functional theory about monads and stuff like that. So don't worry about that. But if we think about a promise as an encapsulation of a value that is time independent, that's what we mean by future value. It's a value that we can reason about right now, regardless of whether the value has been fulfilled or not. And we will reason about it the same way, no matter whether it has ever been fulfilled or not. It's a container. It's a wrapper around a value. We call it a future value. So that transaction was a future value. And the intermediary step that I have for that transaction is the promise. It's that IOU. It's that receipt with an order number. So that's one way of thinking about what promises are going to do is allow us to treat requests for information. It's essentially if you boil it down, whenever you make an asynchronous call or a waiting for a user to click a button or an Ajax call or any of those things, what you're essentially doing is saying, I need some information and it's not ready yet. And whenever you make a request for information, you can model that as saying, I will put that request into a promise. And then I don't have to care as much about when that request gets fulfilled. I don't have to worry about the synchronicity or the asynchronicity. It could finish right now or it could finish 10 weeks from now, but I'm going to reason about it exactly the same regardless. And they're composable in that nature. And I'll show you some code in just a moment. But let me give you a slightly different metaphor for it. What if we could call a function, some third party utility, for instance, and instead of passing them the completion or the continuation of our program, instead of passing a call back in and hoping and trusting and crossing our fingers that they do the right thing, what if we pass that call back in and I'm sorry, what if we don't pass the call back in? We simply call the function and they return to us in some way, shape or form, a way to set up an event handler. For instance, I could call that checkout function and I could get back an event listener. And that event listener, I could listen for both a completion event and an error event. We have un-inverted that process now because rather than giving them control, I have un-inverted and given myself back the control. And I've said, I get to decide what happens next. You just get to notify me that it's time to do that. So in essence, what promises are is a way to do that in a formalized nature. Instead of this sort of weird ad hoc event nature, we have a formalized pattern for it. And that's what we call promises. So imagine if we were to take that track checkout function, if they were a well-behaving company, instead of passing in a call back, we create a promise like we're doing here on line two. We create a promise. And we're going to return that promise back. So that's essentially going to be our event listener. And then inside of that promise, they do whatever they need to do. And they necessarily will then need to call either the resolve function to indicate the completion event or the reject function to indicate the error event. They can do one or the other, not both. And they have as much time as they need to do that because you've returned a promise that is time independent. We can reason about that. We can listen for that event. So what that looks like then in real promise-based code is we listen for the then event, essentially. So you can think of this promise object sort of like an event listener that publishes the then event. And we can listen. The first function, of course, is the successful completion. We have fulfilled the promise successfully. The second one is if the promise failed in some way. Either application logic says I can't fulfill the promise I made. We're out of cheeseburger, sir. I'm sorry, which is totally unacceptable. Or something happens like the building blows up. Your JavaScript fails completely. And some error or some exception occurs. In either case, the error handle gets called in that scenario. So that's another way of thinking about things. Promises as a future value. Promises as an event callback. And there are actually other ways of thinking about it. So I can't be authoritatively covering every single one of those in a short conference talk. But I do encourage you. Hopefully this inspires you to do some more reading. There's some fantastic writing out there on the topic. And whichever one of those metaphors are mixture there of that works, I encourage you. I hope that this inspires you that promises are going to really change the way you reason about the asynchronicity in your code. So promises are designed specifically to solve the problems of inversion of control that we listed earlier. They can only be resolved once. They can only be resolved to success or error, not both. Any messages that are passed along will definitely be kept. They'll be ensured that they get there. Exceptions that occur will be errors. And this last one, which I've highlighted, immutable once resolved, it doesn't get enough attention. But I actually think it's one of the most important intrinsic characteristics of promises is that once that promise has been resolved, nothing from the outside can ever change it or muck with it or change its state ever again. Which is one of the reasons why it now becomes a trustable system. It was time-independent. It didn't really have a value, but we still reasoned about it. As soon as it got the value, now it's just an immutable thing that we can deal with as a value. And that's very, very important. So really, all this is about uninverting that inversion of control, placing the control back in our hands. And that is what promises shine at. So there's another thing that promises also do, which is probably perhaps more common. It's the thing that people spend most of their time focusing on is that promises will allow you to express the flow control of your program through what we call promise chaining. So if I were to talk about pseudocode, and we said it would be nice if I could say, do this first thing, and then do the second thing, and then do the third thing, and then be complete. If we translate that into promise code, it's not quite as nice, but it's really almost the same. We do the first thing, we call the first step, and then we call the then event. So the then event is gonna wrap up the second step. It's not only receiving the value from the first immutable promise, and passing that along if there was a message to pass along, but it is also encompassing that if we create a promise in do second thing and we return it, it will chain together. So the chaining is what allows us to express the flow control the way we want. By returning a promise from the completion handler of a previous promise, they automatically chain together. So when I say do second thing, it will return back and it will chain off of it, do third thing, will also chain off of this one. And of course we can at any step register error handler. If you don't register an error handler, errors will propagate along, so the best practice is always make sure the end of your chain has an error handler and nothing else on it. That way there's no chance that your errors are just gonna fall into the ether. So I wanna give you a couple of more, slightly more concrete scenarios to illustrate how promises are gonna work. The first one I actually, I like this one a lot. If we were loading files in parallel and rendering them in order, in other words, I have file one, file two, and file three, and I wanna render those to my page in order, but I want to load them in parallel for performance and I want them to render as soon as possible. So I don't want for paragraph one to wait around if it's taking a really long time for paragraph two to show up. But by contrast, if paragraph one is taking a really long time and paragraph two comes back quickly, I don't wanna print them out of order. So load in parallel, execute them in order if you will, render them in order, but render them as soon as possible. And that actually turns out to be a generalized statement for an awful lot of complex UI flow can boil itself down to that sort of idea. So I just wanted to show you how you might do that with promises. So up at the top we see I'm creating a promise for each one of my file requests, P1, P2, and P3. Get file is just a normal AJAX response, but an AJAX request, but it returns us back a promise for each one of those. Now P1, P2, and P3 are these future value containers. Whether they finish right away or they take 10 years to complete, I am going to reason about them exactly the same way. So all of that state management that you would normally ad hoc invent externally from that whole functional mode and ad nature that state is encapsulated inside of the promise. And we don't have to worry about it. We just reason about it the right way. So we say P1, and then we say then output P1. Now, if P1 takes a really long time, the output isn't going to go until P1 finishes. If P1 finishes immediately, if it's already in the cache, then it'll immediately go to the next step. But the important part is what you see on line 11. When I return the second promise, what I'm saying is if that promise is finished right away, go ahead and print it. But if it's not yet finished, it's okay because we're going to continue waiting on line 13 as long as it takes. And the same goes for P3, for the promise for the third file. So we can express this chain of flow very simply, and we don't have to worry about any of the state management because promises are designed to compose in very natural ways like this. Now, you may say, that's cool, but what happens when my flow control isn't fixed? What if there isn't just three steps? What if there could be 10 steps on one day and 100 steps on another? I certainly can't write 100 different steps into my chain. That becomes unmaintainable code. And the greatest part of all of this is that promises, because they're sort of a functional concept, they work really well with functional processes like map and reduce. So I can set up an array of requests here. If you don't know about map and reduce, go spend 10 minutes reading on MDN about it. It's a very powerful way of processing infinite lists of things. So I'm going to start out with an array of my file URLs, and I'm going to call the map function. Map is going to call that get file against each item in the array. And it's going to, whatever that returns, it's going to replace that item in the array. So after line two, I now have an array of promises. And then I'm going to call reduce. Now, reduce is what's going to allow me to chain those three independent promises together in exactly the same way as I did it literally in the previous code. It's going to do it through a loop process. So when I reduce, I'm going to start with an empty promise on line 12. And the first iteration, I'm going to chain off of that empty promise the first one, and then output, and then the second one, and then output. So this code maps, if you think about unraveling the loop, it maps exactly to the same logic as in the previous slide. But now it can work for an arbitrary number of steps. Now, let's give a different scenario, a scenario where you want to time out a promise. This is a very common question. What happens if the promise never fulfills itself? Then my program just continues to hang, and I'm going to need some solution for that. Promises have a very good, easy, elegant solution. And the solution that we have is what we call a race. Promises have an abstraction built in them called race, which allows you to take two or more promises and race them against each other. You don't care which one crosses the finish line first, but whichever one does is the one that wins. So we can set up a promise that's hardwired to fail after a certain amount of time, in this case, three seconds. And we can place that in a race against the promise that we care about. And our flow control after this is either going to succeed because the promise happened in less than three seconds, or it will fail because the promise did not happen. And even if that promise completes at a later time, it will just fall into that empty ignored promise. And we don't have to worry about that from a flow control perspective. This is just a very quick illustration of how promises can pose together into more complex patterns for asynchronous flow control. It's very exciting and it's very transformative, and I encourage you to spend some time playing around with it. So I've written an entire five-part blog post series very long and detailed about all of the ins and outs of promises, some of the problems that exist with them because promises do have some rough edges. The native shipped version, they're very low-level building blocks. So in simple cases, they can get the job done. But in more complex cases, sometimes they leave things to be desired. I've talked about that in extreme detail, so you might check out that blog post series. And I've also written a polyfill for promises. If you wanted to get started with promises today, but you wanted to be able to do so in browsers that might not be ES6 compliant, you can drop in a polyfill. It's like 1.2K or something like that. It's a spec compliant polyfill, and it'll let you start doing native raw promises today without any of the overhead of trying to learn somebody else's library. So Harmony does have promises. This is a feature that was added as of ES6. So promises are great, but they do have those rough edges. And that's promise abstraction libraries are still shining today. They were the early adopters of promises. I was one of them. I've been writing promises and promise-based libraries now for over five years. Long before we had official proposals for the spec, we've been playing with these ideas. And there's a lot of fantastic libraries out there for promises. They are designed specifically to extend and provide additional helpers and abstractions and specifically to remove those rough edges from dealing with promises. So I just wanted to point out my particular one, although there are literally dozens and dozens of other ones that you probably have heard of. I'm sure you've heard of Async and Q and WEN and all those others. There's great libraries out there. So my definition of abstraction is that I defined this thing called a sequence, and that is a series of automatically chained promises. If you remember in the previous example, we had to do some kind of manual work. We had to manually create a promise at each step. We had to manually return it so that it would chain together. Because promises themselves as a composable building block are designed, essentially, to just fulfill that one if-then statement, that single fulfillment statement. And it's a little bit more awkward to do the chaining together. My assumption, however, is that most programs are going to have lots and lots of steps. So I created a library called Asinquance, sticking those two words together. And Asinquance basically is designed to assume that you're going to have an infinitely extendable sequence of these steps. It's going to automatically create the promises for you and automatically chain them together so that all you need to do is figure out when it's time to fulfill a particular step's promise. What it does is it looks an awful lot like the Async library. It's doing continuation passing style. It's passing in a callback, which I called done, like you see there on the first line. But it's not like Async in that under the covers, it's using the trustable mechanisms of promises so that you can be guaranteed that this sequence won't go haywire. So Asinquance also has a whole bunch of other wrapper ideas on top of it, abstractions and helpers. For example, the gate, which also is an alias for all. That's how you do two or more things in the same time. And you don't care when they finish. You just want to wait for all of them before you move on. So you can split out into gates and into sub-sequences, however you want to compose them. You might check out Asinquance. If any of that seems interesting, it's designed to be a really small and easy library to kind of get your feet wet. And oftentimes it should be more than enough for what you're going to need for your coding. So I want to go back to that scenario I gave you before about loading files in parallel and just a quick illustration of how Asinquance smooths out a few rough edges. If you remember in the previous slide, we had to, at step two, we had to manually return the promise, the P2, so that it would chain itself in. We can see here that the Asinquance API allows us to automatically do that chaining. So I don't have to create these function wrappers that return promises. I'm calling all three of these promises in parallel, but the sequence chain is designed specifically to consume those promises, those sequences into the chain, and order things properly. That's the power of abstraction libraries is that it makes it even easier. It reduces the mental overhead. And Asinquance can also compose in functional nature. So you see here I'm using two map functions similar to the previous map and reduce. That way you can have an infinitely extending series of sequence steps. So basically, it processes without all the fuss. But that's not where things stop. If that's where things stopped, that would be interesting enough, but actually there's a whole lot more that's at play. So ES6 is also giving us a way to solve this synchronous problem in an even better way than that function, then function, then function, then function style. And that's what we call generators. And I've also written a big long blog post series about generators at that URL. So if you want to read about generators, you can dive into that. But I'll just show you very briefly. Back to our previous example, what you'll notice here is that I'm writing extremely synchronous sequential blocking looking code. The magic of the generator is the yield keyword. At the yield point, it pauses the generator. And what I'm doing here, you'll notice, is that I'm yielding out a promise. So P1 was a promise, and I yielded out that promise. And I have a theoretical library called Run here, which it will run a generator. And if you yield out a promise, it'll listen to that promise and then restart the generator. So this code will run to completion by hiding away the asynchronicity. The asynchronicity is an implementation detail under the covers. And what we write and reason about, our flow control, if you will, is extremely synchronous in nature. So it's now almost perfectly aligned with both the way our brains think and with the way the JavaScript engine exposes these fundamentals to us. That key idea, then, is to have generators and promises together. So there are several libraries out there that have that whole generators plus promises thing in them. A sequence also has that. So one of the benefits is that a sequence lets you go back and forth between promises and generators as you see fit. You don't have to choose one or the other, because I think that the two together are really the best of all worlds. And by the way, if you're worried about generators being syntax that you can't use, there are transpilers for generators. Facebook has one called Regenerator, and there are several others out there. They transpile that generator code into this really ugly looking code, but at least it works. It works, and it will run the same concept, so you've authored very good maintainable code, and it will run in all the browsers that you care about. Even better is that that pattern is so important that there's already a very strongly likely proposal for ES7. We haven't even really hit ES6 yet, and they're already talking about ES7. We're gonna get async functions, which is gonna do exactly the same thing as we just showed before, but you'll notice there's no library wrapper. It will have direct syntactic support in this generator-like function for awaiting a promise rather than yielding out a promise. So this really is representing the future of the language as putting these two things together. Remember, promises are solving the trustability issue, and generators or async functions are solving the synchronous code-looking issue, and by putting those two together, we essentially solve the major problems that callbacks have given us. So I'm excited about ES7. The future of JavaScript is great, but there's one more thing I wanna show you just real quickly. I know, I'm not Steve Jobs, I don't even have the turtleneck, but one more thing I wanna show you, and that's what's called CSP. If you haven't read Hor's book on CSP, Communicating Sequential Processes, it's a fantastic thing, but it's a very deep read, so don't do that unless you have a lot of time to dig into it, but communicating sequential processes essentially in JavaScript, we can implement that as two or more generators that are running at the same time and are cooperatively yielding to each other. So in a sense, what we can do is create a state machine where each state is represented by its own synchronous code-filled generator, and then we can allow generators to yield to each other as you transition back and forth between states. So here, when I am yielding out a promise there, which is just simply gonna return control when that promise finishes, just like before, but when I yield out this token, it's going to transfer control to the generator and then when we yield the token again, it transfers control back. So we can go back and forth between two to many generators and it's unbelievable the amount of complexity that we can express in a very simple, natural way when we start having these capabilities. So, a-sinquence also has that capability built into it automatically. You don't have to jump to some other library to try out that. And there are lots of other things that a-sinquence is packing, so it's got support for this concept of reactive sequences, similar to reactive extensions where you can subscribe to events and fire-off sequences. So there's lots there to uncover and I just encourage you to explore these things, whichever library you use, explore these things because it really is going to change the way you write your code. That's basically the end of my talk and I have a little subtle joke here. If you're not in the promises world, you won't catch that particular joke but there's a bunch in the promises world that wanna add a dot done to the promises spec because there's this problem with losing errors and I think that's a really dumb idea but we're done with the particular talk and I'll leave you as we move into a little bit of Q and A. I'll leave you with this particular mental image. So let's move into some Q and A. I appreciate you tolerating my silliness. Any questions? Yeah. When you want to use promise for a current, like a current code base when you're introducing it, then you run through a problem where you can start writing promise around some code, you don't get to do that and so you have two things running, one is promise base and one is the regular old way of doing it. What's the best pattern to wrap that or can we just, for example, if you get the data and that's promise base but then you're gonna write it out to the DOM and that is not promise base and that's async and so what's the best pattern to do that? Just let it just yolo and just let it do whatever it is. Yeah, that's a fantastic question. So to restate that simply the question is if you can't go fully promises, how do you make promises or promises and generators or whatever play well with the old school callback way of doing things? Now the DOM is actually not a great example because that literally is a synchronous API. It doesn't even involve callbacks but if we were to think about using promises like mechanism alongside a callback mechanism like we see it all over Node.js. The typical pattern in most libraries they call it lifting. In my library, a sequence it's called wrapping but essentially you can take a callback expecting function and produce a promise generating version of that function. So you just do that once at the setup of your program for whichever functions that you need to deal with you just create a wrapped version of it and then in your regular normal code you call those things like they were always promise generating. So that's the most common almost everybody's doing that. All the libraries have some facility for lifting or wrapping callback based ones into a promise based mechanism. That's really the best answer I can give there. Yeah, I run into another concept which sounds very familiar called deferred. So are you familiar with that? Yeah, that was actually one of the original names for part of this promise mechanism. So I was just wondering if you could explain a little history there. I know she didn't use that word so I was wondering is there a conflict or they pretend that others don't exist? Is it one replacing the other? So you want me to give the sorted history of how we move from deferreds into promises. Unfortunately we don't have near enough time for that but I will just say that in the early original days when this was being proposed the promise capability of creating a promise and fulfilling a promise, those two capabilities were separated and the creating a promise capability was called a deferred and the responding to a promise capability was called, I'm sorry, so the resolving was called a deferred and the responding was called a promise and eventually they realized it's too confusing for people to have these two different entities. Let's just put them into one so we just call the whole thing a promise. So that's the 500,000 foot view of how all of that worked out but in jQuery early experimentations in jQuery for instance they had it separated out so that's why you see things like deferred in jQuery just eventually the spec said let's simplify it into one object that we can reason about. Yes, promises are sort of the next step in evolution of all those thoughts. Promises actually come to us as a proposal by Mark Miller from the e-language so it's not actually original art to JavaScript but it's gone through a lot of evolution and what we arrived at now was sort of after all the debates and all the battles we arrived at this nice composable system so all the old school art of it is just informative of how we got to where we are now. Hi, so this is gonna be completely almost off topic question. Okay. What was the best face palm moment you've ever had with respect to sync and what was it like that you just kind of came to see? With respect to sync? Or anything in your last five years of doing this what was your best face palm moment where it all hit you out once? Wow, there are way too many for me to narrow down. I basically look at my evolution as a programmer as failing to success because I learned by doing something wrong and then figuring out how to do it a little bit better and a little bit better and a little bit better. Let me try to think about that and give you a more concrete answer if you'll catch me out or after the book signing I'll try to come up with a slightly better more concrete answer to that question. All right, so I appreciate it very much for you all being here. Don't forget that there are some stickers up here if you want to grab those. I'm going to be doing a book signing immediately after in that the fishbowl room outside. And if this is at all interesting to you, one last plug, the fourth book in the series which I've just started working on, it's all about performance and async. So there's plenty to read about it. Thanks for being here, appreciate it. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you. Thank you.