 Hello, Salt Lake City. So nice to be back in Mountain West. I want to thank Mike for having me again. My talk is on ES 2016. And my talk name has changed slightly because we are now changing the way that we version JavaScript. Starting as of now, we will version JavaScript by years. And so before this was ES 7, now it's ES 2016. A little bit about me. My name is Jabri San. I'm Netflix's cross-team tech UI lead. And I'm a member of the TC39. And that's really why I'm here. ES 2016 features are actually already starting to roll into browsers as we speak. That's not surprising because ES 2016, as the name would indicate, is being developed right alongside 2015. In fact, we're starting to do concurrent development for JavaScript releases. In fact, we've been doing that for quite some time. So that means we can plan ahead as we develop ES 2015 features we've been planning ahead to ES 2016. And this kind of concurrent development allows us to sort of lay in groundwork in the previous version that we can build on top of the next version. So I'm here to tell you a little bit about that story, that continuing story that we're telling in JavaScript and how we're going to use it to this approach to sort of solve some of the hardest problems that the JavaScript community is facing. And the big one I'm here to talk to you about today. ES 2016 is about a lot of things, but I'm going to focus on one particular question today. And that is, how do we make async programming easier? Right? I think that's a pain point for some developers out there. So in ES 2015, or formerly known as ES6, we introduced arrow functions. And arrow functions are a short way of writing a function. Now you can get rid of the boilerplate and write this. That's all I have to say about that. It's pretty great. So they're an improvement. But what if we could write async programs without callbacks at all? Imagine that for a second. I blew a mind over there. So we all know blocking. Blocking is easy. Let's imagine this particular example, get stock price symbol and get symbol price are both using, say, a blocking XHR. Very easy to write this code. Terrible, terrible user experience, right? Because we can't even accept user input while we're going and making these requests. So blocking, from now on when I say blocking, I want you guys to think pulling. What I mean when I say pulling is that we're pulling, as a consumer, we're pulling the value of the function out of the left-hand side. It's being returned in the return position of the function. And so that's how you knew that you're pulling. Data is delivered in the return position of the function. But what if we want to wait instead of block? Well, all of a sudden our code gets a little more complicated. Waiting is another way of saying pushing in JavaScript. What I mean when I say pushing is that we pass in a callback and data is delivered in the argument position of that callback. Notice the difference? We're pulling, data delivered in the return position of the function. When we're pushing, data is delivered in the argument position of a callback. And that's the essence of what pushing is. And in order to wait, without blocking, we need to essentially push in JavaScript. And so that's why we take this, this is the simplest way in which you can push in JavaScript, just pass in a callback. Of course, we find ourselves very quickly in the pyramid of doom. As soon as we start to do anything more complicated, as soon as we start to compose multiple functions together that push, we find ourselves in the pyramid of doom. And so all of a sudden, code on the left-hand side here that's blocking looks way, way worse than the code on the right-hand side. Notice the code on the right-hand side, we've got a lot more code, and all of a sudden we've got code dedicated to something that the JavaScript language usually does for us. Because JavaScript expects you to pull. It expects functions to return in the return position. And as a result, it knows how to deal with throwing, for example, when you throw an exception. Features like try catch handle propagating exceptions for you. But as soon as you do something unexpected, as far as JavaScript is concerned, and decide to return a value in the argument position of a callback, or an error for that matter in the argument position of a callback like they do in Node.js, well, try catch is useless to you. And so all of a sudden you need to write the code that try catch would have written for you as it was. You need to now manually propagate errors. So what if waiting were just as easy as blocking? What if JavaScript understood how to push as well as pull? Promises were something introduced in ES2015. How many people left their hands up know what promises are and how to use them? Quite a few, OK, not everybody. Now, the way to think about a promise is it's a value that represents and eventually realize asynchronous value from a computation. So there's two possible outcomes to a promise. You can call then to get the value out of a promise. And that's as asynchronously it'll be pushed to you in a callback. And there's two possible outcomes. It's succeeded and you get a value. The other is something terrible happened and you got an error. Hopefully there's nobody with epilepsy out there in the cloud. Hopefully you guys can see this, right? So those are the two possible outcomes of a promise. And using promises, we can take this code on the left-hand side and we can rewrite it like this. Notice all of that manual air handling code is gone from here. And it's not because JavaScript got the ability to understand how to do try, catch, on, push. What actually happened was that promises, the type, automatically take errors and forward them up until you provide an error callback. So notice in that function getStockPrice, we aren't doing any air handling whatsoever. Because if a promise detects an error happens in that then method, it'll forward it up to whoever's listening to that promise. And notice here there where I call getStockPrice and I pass in the error callback on the return value, the error effectively will get handled right there. And so the type is doing for us what the language normally does for us. And so that's pretty good. But it still looks awfully different. What if we could code waiting and blocking exactly the same way? What if the code looked almost exactly the same? So here's blocking and waiting. And here's what you can do in ES 2015 to be able to wait and have it look almost exactly like blocking. Not only will this work with try catch, it'll actually work with native control flow structures in JavaScript like while loops for example. Imagine repeating an asynchronous operation with a while loop. So how does this work? Well to explain how this works to you, I need to explain, so here's an example of using a while loop to repeat. In this case I'm gonna try and get the stock price from Bloomberg three times and then I'm gonna give up and I'm gonna go to Yahoo where it might be slightly delayed. So I'm actually using a loop to repeat an asynchronous operation. So how does this magic work? Well I'll explain in just a moment. The thing here, the key thing that I want you guys to understand when you walk out of here is that pushing and pulling are symmetrical. Any value that I can return to you in the return position of a function, I can push to you in a callback. Any error that I can throw from a function, I can push to you in a callback. The reality is the decision about whether to push and pull should be orthogonal to really how that function works with a type of computation that function performs. And so once we decide that pushing and pulling are orthogonal, well we can just have the language support both equally. So we want symmetrical support for both of these things. So in order to explain how that code works, I'm gonna have to explain to you the most powerful and the most misunderstood feature in ES 2015, which is generator functions. Hands up, who's heard of generator functions or is using them? Quite a few people, okay good. So a generator function summed up simply is a way for a function to return multiple values. So we already know a way of a function to return multiple values, right? You stick a bunch of values in an array and you return them. But starting at ES six, you can do this a little more efficiently. Instead of collecting up all the values into an array and then sending that array off, you can generate those values progressively on demand. So this is an example of a generator function that returns three values. Now in this particular example, I want you to think of yield as sort of an intermediary return. It's like okay, I'm gonna return this value intermediary and then finally I'm gonna terminate with my final return value. So what does it look like to consume a data that returns multiple values this way? Well, first you request what's called an iterator from the function. And then you call next and notice what happens on the left hand side? The code begins and pauses at the yield expression and what we get out is a tuple with the value that we got back from the function and a boolean telling us whether we're done or not. Next we call next again because we're not done. We stop at the next yield point, we get out 32 and we find out we're still not done and we call next one final time and we get out 19 and a boolean telling us that we're done. Now I want you to take for a moment, just imagine what it would like to be to write this function without any of this generator function magic, just using plain old ES5. What would you do? Well, you'd probably write a state machine, right? Because every single time you call next, your iterator's in this different state and it has to sort of pick up where it left off. And so here's an example of a Fibonacci sequence which actually goes on forever. If you notice that while true there in the bottom, it's just gonna keep going on forever and how that translates into the code you would write in ES5. So first we return this iterator object but notice we've got this variable that keeps track of what state we're in and every single time somebody calls the next function, we might move through various states. What JavaScript is actually doing here and it's pretty amazing, one of the most amazing compiler transformation that JavaScript does is it's figuring out every possible state that this function could be in. When it's first called, it's in the initial state, right? That's where we're defining those variables. After that, we're yielding the first value and so on and so forth. It's figuring out every possible state that the function could be in and it's turning it inside out. It's turning code that looks like it's pushing into code that's pulling. Imagine that yield keyword, there was a callback and you'll know what I mean, right? We can push, if yield was a callback, we'd sort of be pushing multiple values but it's actually turning it into a pull and this is an amazing transformation and allows us to do some really, really cool things. So finally we can see how these return values match up to the yields. So the way iteration works is you've got a consumer and it requests an iterator from the producer and it just keeps pulling values out of that iterator one at a time and so finally it attempts to pull out a value and it gets a message that it's done and no more and so that's how iteration works. You pull multiple values out of a function until you get an explicit completion message. So if generator functions return to iterators, why aren't they called iterator functions? Well, it's because there's more than meets the eye to generator functions. It's not just about iteration. A generator is actually two different interfaces squashed into one, an iterator and an observer interface. Together, make up a generator interface. So a generator is an iterator, which means it's a data source. You can pull values out of it and there's three types of notifications you can get when you're trying to pull a value out of an iterator. One is you can get the value, that thing that yields. The next is when you try and call next you could get an error thrown at you. Then some sort of error happened while you were trying to pull a value out of this thing. And finally, when you attempt to pull a value out you can get the message that this is the last value, this is the return value and we're done. So value, error, completion. The observer is the other side of the coin. It's actually the push. It's a data sink, not a data source and it's the push equivalent of an iterator. Instead of pulling a value out, you can push a value in by passing a value to next. Furthermore, you can actually send in an error by calling throw. And you can send in a final value by calling return. And so what this really means is that while iteration only allows data to flow one way a generator is a way for two functions to have a long running conversation. I pull a value out, I push a value back in. I pull a value out, I push a value back in. So taking generators and promises we can combine them together to use this pattern known as asynchronous iteration. So what does that mean? Well here I have a function that is basically a generator of promises. Every single time you call next a promise is gonna come out. Get stock symbol, get symbol price returns promises. The other thing I wanna call your attention to is that yield doesn't look like a statement anymore. Before yield just sort of looked like a return. And now it actually looks like an expression. So when we actually push a value back into a generator it replaces the yield expression. So we're gonna see how that works in a second. So here's the consumer. This spawn function is going to return a promise that will be the eventual result of get stock price. So together they essentially make get stock price like an asynchronous function. And I'll show you how that interaction works in just a second. The way ace have spawn function consumes this generator of promises resolves them until it finally gets to the last value and then resolves the big final promise to that value, the value that comes out of spawn. So asynchronous iteration works like this. If I run this function it'll run through all these promises get stock symbol, get stock price and then finally arrive at the final value and print it out. So asynchronous iteration is pretty much the same as iteration. The consumer requests a generator from the producer, requests a value. Now notice here on the right hand side we pause at the yield expression and what's being yielded a promise. And so a promise comes out of the producer and the consumer and the producer have an agreement. The consumer agrees that whenever the producer gives it a promise it's gonna resolve that promise and send push the value back in. And so the consumer resolves the promise by calling then it gets out the value PFE which is the stock symbol and it calls next again but this is crucial. Notice that this time when it calls next it's actually passing in the result of the promise as an argument to next. So it's pushing a value in at the same time as it's trying to pull the next value out. What happens to that PFE value? This entire yield expression gets replaced by the value that comes back in and the code continues on to the next yield expression and it pauses. We generate a promise handed to the consumer. The consumer attempts to resolve that promise in the same manner as before, takes the value which is this 2783 it's the stock price value, pushes it back in and now the yield expression gets replaced with this value and we continue the function. So finally we get the final value, we return it and say that you know what no more values are coming out and now at this point the consumer takes which is spawn, that spawn function resolves the big promise to be 2783. So pictures are great but let's actually take a look at some code. So this is a very simplified version of how this works. You've got a producer up top which is this generator function that generates promises and you've got a consumer down here at the bottom which is consuming those promises, resolving them and sending the value back in until the generator says you know what no more values, here's the final value and then the overall promise is resolved to that. See if I can steady this a little bit. What's going on here, just to refresh your recollection is a consumer is pulling promises out of a producer of a generator of promises and resolving them and sending them back in until the generator says you know what I'm done and then the overall promise that's the result of this whole computation up top there gets stock price will resolve with that final value. So let's see how it works. We've got this spawn function which is the consumer of the generator and so here down here we're gonna execute this code and then we immediately begin inside of the body of the promise. So this, all you see here return new promise. We're creating a new promise and that accept and reject function are the function that we're gonna call to resolve to the final value of the promise or the reject function we wanna call if there was an error. And so I've created this on result function which is we're gonna call every single time a promise gets resolved with the result of that promise. Now the very first time though there's no result of a promise so we're just gonna call it with no arguments and we're gonna jump up here and we're going to call next, we're gonna call next and notice here that arrow just starts right there at the first yield point. We get out a promise so that resolves to a promise and we get out the promise and then a boolean indicating we're not we're done. So since we got a promise we're gonna attempt to resolve that promise and then we're gonna pass in on result recursively. So now when on result gets called it'll actually have the result of that last promise which will be Johnson and Johnson. And so we repeat the process we request the next value from the generator and we jump to the next yield point or excuse me, first we push in Johnson and Johnson by calling next and passing it as an argument notice how that yield expression up top gets replaced with Johnson and Johnson and the code just keeps going until the next yield point at which point we yield the price promise we get the promise out as the consumer I pulling the promise out and then I'm gonna go ahead and resolve it and recursively pass in on result and this time when on result gets called it gets a result of the price. So we take that value and once again we pass it we push it back into the generator and the yield expression up top gets replaced with the value. Finally we terminate at the return value we get the final value done is true and so we skip over we don't try and resolve a promise because we didn't get one we accept the final value and out it comes. So it's pull and push we're actually pulling promises out realizing them and then pushing them back in and this asynchronous iteration pattern is what allows us to write code that looks like it actually blocks but it waits. So your code can get so much simpler here without a single callback at least outside of the spawn function which only has to be written once you can write code that's asynchronous but looks like it's synchronous. And so the stuff I'm talking about is all the version of JavaScript which is just finalized the version of JavaScript that will be making its way into browsers in the next few months. In fact this generator feature and promises can already grab this from the latest version of V8 and Firefox. So this is what it looks like waiting. So this spawn function actually comes from TaskJS so which is a library you can go check out right now it works together with generators to allow you to write this code and that defines the spawn function right here. So you can try this today you don't even need to wait for ES 2016. In fact I haven't told you about a single feature from ES 2016 yet. So it's TaskJS you can go check it out right there you wanna start playing around with this stuff you're using generators already. But that begs the question. Why should waiting require a library? Why should I need to go download TaskJS? Why shouldn't JavaScript have native support for pushing and pulling, waiting and blocking? And so that with this we come to the first ES 2016 feature I wanted to talk to you guys about today. Asynchronous functions. So we can take, we can use asynchronous functions in ES 2016 and turn waiting here into waiting here. Notice the presence of the new async keyword as well as the new await keyword. Under the hood this pretty much just de-sugars to what you see on the left hand side here. Now you know what this does it's a pretty much straight forward de-sugaring to this pattern of asynchronous iteration. But instead of yield we have a wait we don't have a function star we just have a regular function. And that's how it's gonna work in ES 2016 to write async functions. Now if you just wanna wait and do a bunch of operations sequentially one after the other you can do that without callbacks. And you can use loops, try catch and all that stuff you're used to for blocking code. So symmetrical support for blocking and waiting is coming in ES 2016, right? And what language does it make more sense for than JavaScript? Which is single-threaded where you have to do callbacks all the time. So whenever you're talking about the features that are coming in ES 2016 it's really important to be responsible and talk about maturity stages. Now there have been changes to features at the penultimate hour in ES 2015 and there may be changes in ES 2016. So it's important to talk about where it is in these feature maturity stages. This is how we communicate with developers about how mature these various features are. So async functions are currently in the draft stage. And another way of saying that is the community expects the feature to be developed and included in the standard. So we're pretty confident there may be some changes but that we're pretty confident is gonna make it into ES 2016. So you can try async functions now. You can actually go to Facebook's regenerator transpiler which will go and download the async await branch. And now you can run that code over your code and start playing with async await today. In fact, that's very much what we in the committee would like you to do. Part of the reason why we work on these transpilers is so that you guys can try them out, give us some feedback and tell us what works and doesn't work for you. So if you wanna play around with it you can absolutely do that today. So the await keyword makes it really easy to wait on one asynchronous value. But what if you wanna wait on a bunch of asynchronous values? Can anybody think of a type that sends a bunch of different asynchronous values one after the other? Node programmers, anything come to mind? Event emitter, yeah, that's a good one. How about just DOM events, right? These are all things that push you multiple values and you have to wait on them. So, oops, I lost power here. In ES6, all collections are iterable and this is a new contract in ES6. Iterable means you can walk up to it, ask it for an iterator, and then pull values out until you get a completion message. And so the array, the new map method, excuse me, new map type in ES2,060 or 215 are iterable. And so it's this common contract. You can walk up to an array and use this new symbol iterator key to pull out an iterator and then you can just while loop over it. But we also have this helpful syntax. So this new for of loop, it's not a for in loop, it's a for of loop, which is designed specifically to do what you're seeing on the left-hand side here. You don't have to write all this boilerplate to iterate over something. What you see on the right-hand side transpiles into what's on the left-hand side and there's a new for of loop specifically for doing iteration, because it's such a common pattern. I just wanna consume items out of this producer one item at a time. I wanna pull them out. So here's how you would wait on values using for on. There's, oh, excuse me. There's a new loop that we're trying to introduce in ES 2016 called for on. Wouldn't it be great if you could for loop over a web socket or a stream or a DOM event? What would it mean to for loop over a DOM event? Well, we know that streams push multiple values and then push a completion message. If I can for loop over an iterator, why can't I for loop over a stream? I don't need a callback. The callback is really just machinery. Pushing and pulling are symmetrical. And so if I should be able to loop over values I can pull, I should be able to loop over values that are pushed at me. So I want you to notice very carefully. This is different than the loop we saw before. It's a for on loop. I'm looping over this web socket and I'm trying to grab the first price with a price spike over a certain threshold. And so if I run this, it'll go over and it eventually find a price that spikes and it'll give me a value. So imagine being able to for loop over streams of values being pushed at you. There's a problem with doing this. We'd love to do this, but there's a little bit of a challenge. And that is that the web has no standard observable interface, right? You've got streams, you've got DOM events, you've got web sockets, you've got jQuery events, you've got server cent events, XML HTTP request has a progressive mode. Cent interval is technically a stream of values in one way of thinking about it, right? Node streams, all of these things are about the same thing. They're about pushing you values one after another, but there's no one common interface for them. Unlike now in ES6, this iterator, iterable interface, what we really need is a type specifically for that that all of these different contracts can implement. And so introducing the observable type. The observable is actually hidden in JavaScript 2015 right now. It's hidden in there. You have to find it, but you can find it. All you do is you take the iterable interface, which will give you a generator when you call iterator on it, and you turn it around. You swap the arguments and the return type, and what you've got is an observable. Remember that a generator is double-sided. It's both the data source and something you can pull values out of, and it's also a data sink, something you can push values into. And so the way an observable works is it accepts the generator and pushes values into it. So it's like passing three callbacks, right? A generator is like three callbacks, next, throw and return. Observer is like three callbacks. It's like passing three callbacks to a data source and having it push values at you. And you can express DOM events this way. You can express Node Streams this way. You can express WebSockets this way. You have an explicit error or explicit completion message. So now that we have this observable type, let's take a look at what this looks like. We'll take iteration, and now let's contrast it with observation. The truth is iteration and observation are both about the same thing. They're both about a producer giving a consumer one item at a time until finally they say we're done or an error occurs. The difference is who's in control. In iteration, the consumer's in control and it's pulling values out. In observation, the producer's in control. And so the consumer hands the producer an observer, which is those three methods, next, throw and return, it's like three callbacks. And the producer pushes values to the consumer by invoking those next return and throw methods. I'm just gonna keep pushing values to the consumer until finally I push the final value, return, no value there, and just saying it's done. So it's the same thing as iteration just backwards. We're only beginning in this industry in the last five or six years to understand the deep symmetrical relationship between pulling and pushing. Once you realize that observation and iteration are just two different ways of doing the same thing, you can look at it more closely and make sure that you're not making, they're essentially orthogonally your function. You can make sure that you can write code the same way regardless of whether you're iterating and observing. Because it really doesn't matter. It's orthogonal to what your function does, which is produce values from inputs. And so your language is to support both equally. So here's what it looks like, kind of de-sugared in code. I'm basically passing this object with three callbacks into an observable. And as soon as I run this, it's just gonna push me a bunch of values and then done. So like adding three callbacks to a DOM event, for example. So we can add a little sugar to this. So there's a for each method that returns a promise. That's one way of doing it. It'll tell you when it's done or whether there's an error. And inside of an async function, which is going to resolve to a promise anyways, which is asynchronous, you can use this for on loop to consume any observable. And it's basically gonna consume all the data in the observable before it continues. And what we hope is that once we've got this observable API standardized, all of these different sources will implement observable. And you'll basically have one interface for observation on the web. And that's what you need to have in order to add language support. So consuming observables at ES 2016, looks something like this. I can just run this. Just this code can go on forever. I can just keep logging the Netflix members to the join, for example. Now we have an async function and we have a function star. And as language designers, that creates a little problem for us. If an async function returns a promise and a function star returns an iterator, what does an async function star return? It's up to us as language designers to be able to answer these questions, right? Well, let's take a look at it. We've got this sort of missing piece here, right? We've got a synchronous function which returns some value. We have a asynchronous function which returns a promise. We've got a synchronous function star, generator function which returns an iterator or a generator depending on your perspective. There's this big missing quadrant. What does it return? Well, if a function star returns multiple values and an async function pushes one value, an async function star pushes multiple values. What's the type that pushes multiple values? Unobservable. So now that we've got this interface, we can actually have an asynchronous generator function that pushes multiple values over time. So this is something that's being proposed for ES 2016. So you could create, for example, a function that foreons over a web socket and then yields values out. Basically transforms the stream but still stays a stream. So here's an example of that in action. So before, we got the first price spike and we printed it out. Now we're gonna create a stream of all the price spikes. We're gonna listen to a web socket for prices for a particular stock and every single time the previous price and the new price exceeds a certain threshold, we're gonna emit it. So if I run this, it's gonna get values like that forever. I can produce something that I can once again foreon over. Symmetrical support for functions that return multiple values, whether they push them or pull them. So for more information on async function star, you can check out this GitHub where the information about the proposal exists. We're hoping to have some specification language on this for the next TC39 meeting in Paris. And so it's important to my notice though, this is at the straw man phase of proposal, which is the earliest possible stage. We're still looking for feedback. There's still a lot of details to be worked out but async functions are a good deal further along the specification process in this. So at this phase, we're just allowing for feedback. We're looking for people to give us feedback about this proposal and whether it helps solve their problems. So here are some resources you can check out. One is my Twitter handle where I announce a lot about this. Netflix UI Engineering, which is the YouTube channel. You wanna check out this talk, it's already up on YouTube in a little more detail. And esdiscuss.org is where you can go and give feedback to the committee about features that are proposed for JavaScript. Regenerator can be found here, TaskJS and once again the async generator specification. Okay, thanks everybody.