ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest...

125
ES7 The Evolution of JavaScript

Transcript of ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest...

Page 1: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

ES7

The Evolution of JavaScript

Page 2: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Who is Jafar Husain?

•  Architect of Falcor, Netflix’s OSS data platform

•  Netflix representative TC-39 •  Formerly worked for MS and GE

Page 3: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

June 2015

ES6 spec will be finalized in

Page 4: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Isn’t it too early to talk about ES7?

Page 5: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

No.

Page 6: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

ES7 features are already starting to roll into browsers.

Page 7: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

ES7

ES6

ES5

Page 8: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

ES7 ES6

Page 9: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

BIG 2ES7

Page 10: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

#1

Page 11: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Easier Model/View Synchronization

Model View

Page 12: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

#2

Page 13: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Easier Async Programming

pull

push

Page 14: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Arrow Functions

ES6

=>  

Page 15: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Arrow Functions

x  +  1  function(x)  {  return  x  +  1;  }    

x   =>    function(x,  y)  {  return  x  +  y;  }  (x,  y)  

   

x  +  y      

 =>      

ES 6 5

Page 16: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Controller

View Model

Page 17: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)
Page 18: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Why not natively support change notification?

?

Page 19: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Object.observe

ES7

Page 20: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Object.observe

var  person  =  {};    var  changesHandler  =  changes  =>  console.log(changes);  Object.observe(person,  changesHandler);  

Page 21: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Object.observe person  =  {        name:          

[          {                  "type":”new",                  "name":”employer”          }  ]  

[          {                  "type":”update",                  "name":”name”,                  “oldValue:  “Dana  Miller”          }  ]  

“Dana  T.  Miller”  “Dana  Miller”  };    

                                           ,  employer:  “Tommy's  Box  Store”  

[          {                  "type":”reconfigure",                  "name":”name”          }  ]  

[          {                  "type":”delete",                  "name":”employer”,                  “oldValue:  “Tommy's  Box  Store”          }  ]  

Page 22: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Object.unobserve

Object.unobserve(person,  changesHandler);    

Page 23: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

unobserve    The  word  you’ve  entered  isn’t  in  the  dic2onary.    

irregardless    regardless.    

Page 24: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Event Handler Browser render XHR handler Timeout

handler

Tasks on the event loop

The Event Loop Queue

Observe notification

person.name  =  “Jim”;  person.age  =  22;  

Current Task

Page 25: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

How to avoid the

Notification Storm? How to avoid the

Notification Storm?

Page 26: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Microtasks

ES6

Page 27: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Event handler Browser render XHR handler Timeout

handler

Tasks on the event loop

Event Loop Queue + Microtasks

Observe handler

Current Task

person.name  =  “Jim”;  person.age  =  23;  

Page 28: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

sync sync

Object.observe on Microtasks

Model A Model B DOM

Page 29: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Try Object.observe

Page 30: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Object.observe

Page 31: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

ES Feature Maturity Stages

0. Strawman 1. Proposal 2. Draft 3. Candidate 4. Finished

Page 32: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Maturity Stage 2: Draft

“Commi&ee  expects  the  feature  to  be  developed  and…included  in  the  standard.”  

Page 33: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

How can we make async programming easier?

?

Page 34: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Blocking is Easy

function  getStockPrice(name)  {          var  symbol  =  getStockSymbol(name);          var  price  =  getStockPrice(symbol);          return  price;  }      

Page 35: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Blocking means Pulling

     price  =  getStockPrice(“Devine  Inc.”);  

Data delivered in return position

pull

Page 36: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

What if we want to wait instead of block?

?

Page 37: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Waiting means Pushing

     getStockPrice(“Devine  Inc.”,  price  =>  {  …  });  

Data delivered in argument position

push

Page 38: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

The Pyramid of

DOOM

Page 39: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Blocking/Pulling

function  getStockPrice(name)  {          var  symbol  =  getStockSymbol(name);          var  price  =  getStockPrice(symbol);          return  price;  }      

Page 40: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Waiting/Pushing function  getStockPrice(name,  cb)  {          getStockSymbol(name,  (error,  symbol)  =>  {                  if  (error)  {                          cb(error);                  }                  else  {                          getStockPrice(symbol,  (error,  price)  =>  {                                  if  (error)  {                                          cb(error);                                  }                                  else  {                                          cb(price);                                  }                          })                  }          })  }      

function  getStockPrice(name,  cb)  {          getStockSymbol(name,  (error,  symbol)  =>  {                  if  (error)  {                          cb(error);                  }                  else  {                          getStockPrice(symbol,  (error,  price)  =>  {                                  if  (error)  {                                          cb(error);                                  }                                  else  {                                          cb(price);                                  }                          })                  }          })  }      

Page 41: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Pulling and Pushing

are symmetrical

Page 42: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Why must waiting be so much harder than blocking?

?

Page 43: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Promises

ES6

Page 44: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Promises

42   X  promise.then(value  =>  {…},  error  =>  {…});  

Page 45: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

function  getStockPrice(name)  {          var  symbol  =  getStockSymbol(name);          var  price  =  getStockPrice(symbol);          return  price;  }      function  getStockPrice(name)  {          return  getStockSymbol(name).                    then(symbol  =>  getStockPrice(symbol));  }  

sync

async  

Page 46: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Not bad, but…

Page 47: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

…why does waiting have to look so different than blocking?

?

Page 48: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

function  getStockPrice(name)  {          var  symbol  =  getStockSymbol(name);          var  price  =  getStockPrice(symbol);          return  price;  }  

function  getStockPrice(name)  {          return  getStockSymbol(name).                    then(symbol  =>  getStockPrice(symbol));  }  

sync

async  function*  getStockPrice(name)  {          var  symbol  =  yield  getStockSymbol(name);          var  price  =  yield  getStockPrice(symbol);          return  price;  }  

Page 49: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Generator function

ES6

Page 50: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

A generator function can return multiple values.

96  23  done  

Page 51: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Generator Functions in ES6

function*  getNumbers()  {          yield  42;          yield  32;          return  19;  }  

Page 52: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Retrieving function* results function*  getNumbers()  {          yield  42;          yield  32;          return  19;  }  >  var  iterator  =  getNumbers();  

>  {  value:  42,  done:  false  }  >    

>  console.log(iterator.next());    

>  console.log(iterator.next());    >  {  value:  32,  done:  false  }  >  >  console.log(iterator.next());    >  {  value:  19,  done:  true  }  >  

Page 53: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iteration

42  

Consumer Producer

var  result  =  iterator.next()  var  iterator  =  producer.iterator();  

Page 54: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iteration

39  

Consumer Producer

var  result  =  iterator.next()  

Page 55: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iteration

done  

Consumer Producer

var  result  =  iterator.next()  

Page 56: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

How Yield Works

function  getFibonnacciSequence()  {          return  {                  next:  function()  {                          let  val1  =  0,  val2  =  1,  swap,  state  =  0;                          switch(state)  {                                  case  0:                                          state  =  1;                                          return  {value:  val1,  done:  false};                                  case  1:                                          state  =  2;                                          return  {value:  val2,  done:  false};                                  default:                                          swap  =  val1  +  val2;                                          val2  =  swap;                                          val1  =  val2;                                            return  {value:  swap,  done:  false};                          }                  }          }  }  

function*  getFibonnacciSequence()  {                      let  val1  =  0,  val2  =  1,  swap;                        yield  val1;                      yield  val2;          while(true)  {                  swap  =  val1  +  val2;                  val2  =  swap;                  val1  =  val2;                  yield  swap;          }  }  

function  getFibonnacciSequence()  {          return  {                  next:  function()  {                          let  val1  =  0,  val2  =  1,  swap,  state  =  0;                          switch(state)  {                                  case  0:                                          state  =  1;                                          return  {value:  val1,  done:  false};                                  case  1:                                          state  =  2;                                          return  {value:  val2,  done:  false};                                  default:                                          swap  =  val1  +  val2;                                          val2  =  swap;                                          val1  =  val2;                                            return  {value:  swap,  done:  false};                          }                  }          }  }  

function  getFibonnacciSequence()  {          return  {                  next:  function()  {                          let  val1  =  0,  val2  =  1,  swap,  state  =  0;                          switch(state)  {                                  case  0:                                          state  =  1;                                          return  {value:  val1,  done:  false};                                  case  1:                                          state  =  2;                                          return  {value:  val2,  done:  false};                                  default:                                          swap  =  val1  +  val2;                                          val2  =  swap;                                          val1  =  val2;                                            return  {value:  swap,  done:  false};                          }                  }          }  }  

function  getFibonnacciSequence()  {          return  {                  next:  function()  {                          let  val1  =  0,  val2  =  1,  swap,  state  =  0;                          switch(state)  {                                  case  0:                                          state  =  1;                                          return  {value:  val1,  done:  false};                                  case  1:                                          state  =  2;                                          return  {value:  val2,  done:  false};                                  default:                                          swap  =  val1  +  val2;                                          val2  =  swap;                                          val1  =  val2;                                            return  {value:  swap,  done:  false};                          }                  }          }  }  

Page 57: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

All ES6 collections are Iterable.

ES6

Page 58: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iterator Pattern

>  var  iterator  =  [42,  39][@@iterator]();  

>  {  value:  42,  done:  false  }  >    

>  console.log(iterator.next());    

>  console.log(iterator.next());    

>  {  value:  39,  done:  false  }  >  >  console.log(iterator.next());    >  {  done:  true  }  >  

Page 59: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Consuming Iterables with for..of

>  for(var  x  of  [42,39,17])  {              console.log(x);      }    >  42    >  39  >  17  >  

Page 60: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

If generator functions return iterators…

Page 61: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

…why aren’t they called Iterator functions?

?

Page 62: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iterator Observer Generator

Page 63: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

A Generator is an Iterator

yield value

throw an error

return value  

generator.next().value;  

try  {  generator.next();  }  catch(err)  {  ...  }  

var  pair  =  generator.next();  if  (pair.done)  alert(pair.value);  

pull

Page 64: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

A Generator is an Observer

receive data

receive an error

receive return value  

generator.next(5);  

generator.throw(“fail”);  

generator.return(5);  

push

Page 65: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iteration only allows data to flow one-way.

96  23  done  

Page 66: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Generators allow feedback.

96  33  21  99  done  

Page 67: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Waiting with Async Iteration function*  getStockPrice(name)  {          var  symbol  =  yield  getStockSymbol(name);          var  price  =  yield  getStockPrice(symbol);          return  price;  }    >  spawn(getStockprice(“Pfizer”)).              then(                      price  =>  console.log(price),                      error  =>  console.error(error));        

>    353.22  

Page 68: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

“PFE”  

Async Iteration Consumer Producer

var  result  =  generator.next()  var  generator  =  getStockPrice(‘Pfizer’);  var  symbol  =  yield  getStockSymbol(‘Pfizer’);  result.then(data  =>  …,  error  =>  …)  

Page 69: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

27.83  

Async Iteration Consumer Producer

var  result  =  generator.next(“PFE”)   var  symbol  =  yield  getStockSymbol(‘Pfizer’);  

“PFE”  

var  symbol  =  “PFE”  var  price  =  yield  getStockPrice(symbol);  result.then(data  =>  …,  error  =>  …)  

Page 70: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Async Iteration Consumer Producer

var  result  =  generator.next(“27.83”)   var  price  =  yield  getStockPrice(symbol);  

27.83  

var  price  =  27.83  return  price  

done  

Page 71: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

function*  getStockPrice(name)  {          var  symbol  =  yield  getStockSymbol(name);          var  price  =  yield  getStockPrice(symbol)          return  price;  }    function  spawn(generator)  {          return  new  Promise((accept,  reject)  =>  {                            var  onResult  =  lastPromiseResult  =>  {                            var  {value,  done}  =  generator.next(lastPromiseResult);                            if  (!done)  {                                    value.then(onResult,  reject);                            }                            else  accept(value);                  };                  onResult();          });  }    >  spawn(getStockPrice(“Johnson  and  Johnson”)).then(console.log);  

“JNJ”  

pricePromise;  symbolPromise;  

Asynchronous Iteration

420.25  

“JNJ”  

“JNJ”;  

420.25  420.25  

420.25;  

>  

function*  getStockPrice(name)  {          var  symbol  =          var  price  =          return  price;              }    function  spawn(generator)  {          return  new  Promise((accept,  reject)  =>  {                            var  onResult  =                              if  (!done)  {                                    value.then(onResult,  reject);                            }                            else  accept(value);                  };                  onResult();          });  }    >  spawn(getStockPrice(“Johnson  and  Johnson”)).then(console.log);§  

           function  spawn(generator)  {          return  new  Promise((accept,  reject)  =>  {                                    });  }                                                                                                then(console.log);  

{value:  symbolPromise,  done:  false};  {value:  pricePromise,  done:  false};  {value:  420.25,  done:  true};  

producer

consumer

Page 72: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Waiting with with Task.js

function*  getStockPrice(name)  {          var  symbol  =  yield  getStockSymbol(name);          var  price  =  yield  getStockPrice(symbol);          return  price;  }    var  result  =            spawn(getStockPrice.bind(null,  “Pfizer”));    result.then(console.log,  console.error);  

Page 73: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Get Task.js

Page 74: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Why should easy waiting require a library?

?

Page 75: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Async Functions

ES7

Page 76: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Async Functions in ES7

function*  getStockPrice(name)  {          var  symbol  =  yield  getStockSymbol(name);          var  price  =  yield  getStockPrice(symbol);          return  price;  }    var  result  =  spawn(getStockPrice.bind(null,  “PFE”));  result.then(console.log,  console.error);  

async  function  getStockPrice(name)  {          var  symbol  =  await  getStockSymbol(name);          var  price  =  await  getStockPrice(symbol);          return  price;  }    var  result  =              getStockPrice                      (“PFE”)  ;  result.then(console.log,  console.error);  

Page 77: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

function  getStockPrice(name)  {          var  symbol  =  getStockSymbol(name);          var  price  =  getStockPrice(symbol);          return  price;  }    async  function  getStockPrice(name)  {          var  symbol  =  await  getStockSymbol(name);          var  price  =  await  getStockPrice(symbol);          return  price;  }  

sync

async  

Page 78: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Symmetrical support for push and pull functions.

ES7

Page 79: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Async Functions

Page 80: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Try Async Functions

Page 81: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

The await keyword makes it easy to wait on an async value…

Page 82: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

…but what if you need to wait on

? an async stream of values?

Page 83: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Waiting on a stream with for…on async  function  getNextPriceSpike(stock,  threshold)  {          var  delta,                  oldPrice,                  price;            for(var  price  on  new  WebSocket(“/prices/"  +  stock))  {                  if  (oldPrice  ==  null)  {                          oldPrice  =  price;                  }                  else  {                          delta  =  Math.abs(price  -­‐  oldPrice);                          oldPrice  =  price;                          if  (delta  >  threshold)  {                                  return  {  price:  price,  oldPrice:  oldPrice  };                          }                  }          }  }    >  getNextPriceSpike(“JNJ”,2.50).then(diff  =>  console.log(diff));  >  {  price:  420.22,  oldPrice:  423.19  }  

Page 84: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Unfortunately there’s a problem.

Page 85: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

The web has no standard Observable interface.

Page 86: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iteration Consumer Producer

Observation Consumer

Page 87: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

b  b  b  b  

42  

Consumer Producer

observer.next(42)  

Observation

39  done  

observer.return()   producer.observer(observer);  observer.next(39)  

Page 88: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

The Web’s Many Observable APIs •  DOM Events •  Websockets •  Server-sent Events •  Node Streams •  Service Workers •  jQuery Events •  XMLHttpRequest •  setInterval

push

Page 89: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

interface  Iterable  {    Generator  iterator(void);  

}  

Introducing Observable

interface  Observable  {                  observer(Generator);  

}  void  

Page 90: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Observer pattern

>  nums().observer({            next(v)  {  console.log(v);  },          return(v)  {  console.log(“done:”  +  v);  }          throw  (e)  {  console.error(e);  },  });            >  1      

>  2      

>  done:  3      

Page 91: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Adding Sugar to Observation nums().observer({            next(v)      {    console.log(v);  },          return(v)  {    console.log(“done:”  +  v);  }          throw  (e)  {    console.error(e);  },  });  

nums().          forEach(v  =>  console.log(v)).            //  next          then(      v  =>  console.log(“done:”),  //  return                          e  =>  console.error(e));        //  throw              (async  function  writeNums()  {          try  {                  for(var  v  on  nums())  {                        console.log(v);                }          }  catch(e)  {  console.error(e);  }          console.log(“done”);  })();            

Page 92: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Push APIs implement Observable

DOM Events Websockets Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval

Observable

Page 93: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Implementing Observable WebSocket.prototype.observer  =  function(generator)  {          var  cleanUp,                  message  =  v  =>  {                          var  pair  =  generator.next(v);                          if  (pair.done)                                  cleanUp();                  },                  error  =  e  =>  {                          cleanUp();                          generator.throw(e);                  },                  close  =  v  =>  {                          cleanUp();                          generator.return(v);                  };            cleanUp  =  ()  =>  {                  this.removeEventListener(“message”,  message);                  this.removeEventListener(“error”,  error);                  this.removeEventListener(“close”,  close);          };          this.addEventListener(“message”,  message);          this.addEventListener(“error”,  error);          this.addEventListener(“close”,  close);  };  

Page 94: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Consuming Observables in ES7

>  (async  function()  {    for(var  member  on  new  WebSocket(“/signups”)){  

               console.log(JSON.stringify(member));          }  }());  

>  {  firstName:  “Tom”  …  }      >  {  firstName:  “John”  …  }      >  {  firstName:  “Micah”  …  }      >  {  firstName:  “Alex”  …  }      >  {  firstName:  “Yehuda”  …  }      >  {  firstName:  “Dave”  …  }      >  {  firstName:  “Ben”  …  }      >  {  firstName:  “Dave”  …  }      

Page 95: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Observable Composition async  function  drag(element)  {        var  downs  =  Observable.fromEvent(element,  “mousedown”);        var  ups  =  Observable.fromEvent(document,  “mouseup”);        var  moves  =  Observable.fromEvent(document,  “mousemoves”);          var  drags  =                  downs.                        map(down  =>  moves.takeUntil(ups)).                        flatten();  

     for(var  drag  on  drags)  {  

             element.style.top  =  drag.offsetY;                element.style.left  =  drag.offsetX;    

 }  }  

Page 96: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Try Observable

Page 97: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

If an async function returns a Promise,

and a function* returns an Iterator…

Page 98: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

…what does an async function* return?

?

Page 99: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Function Types in ES7

Synchronous Asynchronous

function T Promise

function* Iterator

Page 100: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

A function* returns multiple values.

96  23  done  

Page 101: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

An async function pushes one value.

96  

Page 102: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

An async function* pushes multiple values.

96  23  done  

Page 103: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

An async generator function returns an Observable.

b  

Page 104: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Async generator functions

ES7

b  

Page 105: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

async function* in action async  function*  getPriceSpikes(stock,  threshold)  {          var  delta,                  oldPrice,                  price;            for(var  price  on  new  WebSocket(“/prices/"  +  stock))  {                  if  (oldPrice  ==  null)  {                          oldPrice  =  price;                  }                  else  {                          delta  =  Math.abs(price  -­‐  oldPrice);                          oldPrice  =  price;                          if  (delta  >  threshold)  {                                  yield  {  price:  price,  oldPrice:  oldPrice  };                          }                  }          }  }    

Page 106: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Consuming Observables in ES7

>  async  function  printSpikes()  {                for(var  spike  on  getPriceSpikes(“JNJ”,  2.00))  {                        console.log(priceSpike);                }      }());  >  {  oldPrice:  392.55,  price:  396.82  }      >  {  oldPrice:  397.14,  price:  395.03  }      >  {  oldPrice:  394.18,  price:  392.01  }      >  {  oldPrice:  392.55,  price:  400.92}      >  {  oldPrice:  401.53,  price:  403.12}      >  {  oldPrice:  404.22,  price:  407.74}      >  {  oldPrice:  403.28,  price:  405.88}      >  {  oldPrice:  406.18,  price:  409.29}      

Page 107: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

ES7 should have symmetrical support for push and pull streams.

Page 108: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

How can we make async I/O easier?

?

Page 109: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Sync I/O is easy with function* function*  getStocks()  {  

 var  reader  =  new            FileReader(“stocks.txt”);    try  {        while(!reader.eof)  {        var  line  =              reader.readLine();        yield  JSON.parse(line);  

                   }    }    finally  {      reader.close();    }  

}    function  writeStockInfos()  {  

 var  writer  =  new            FileWriter(“stocksAndPrices.txt”);    try  {      for(var  name  of  getStocks())  {        var  price  =              getStockPrice(name);        writer.writeLine(JSON.stringify({name,  price}));      }    }    finally  {      writer.close();    }  

}  

producer

consumer

Page 110: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Async I/O with async function* async  function*  getStocks()  {  

 var  reader  =  new  AsyncFileReader(“stocks.txt”);    try  {        while(!reader.eof)  {        var  line  =  await  reader.readLine();        await  yield  JSON.parse(line);  

                   }    }    finally  {      await  reader.close();    }  

}    async  function  writeStockInfos()  {  

 var  writer  =  new  AsyncFileWriter(“stocksAndPrices.txt”);    try  {      for(var  name  on  getStocks())  {        var  price  =  await  getStockPrice(name);        await  writer.writeLine(JSON.stringify({name,  price}));      }    }    finally  {      await  writer.close();    }  

}  

producer

consumer

Page 111: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

b  b  b  b  

42  

Consumer Producer

Async Observation

39  done  

Page 112: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Async IO with async function* async  function*  getStocks()  {  

 var  reader  =  new  AsyncFileReader(“stocks.txt”);    try  {        while(!reader.eof)  {        var  line  =  await  reader.readLine();        await  yield  JSON.parse(line);  

                   }    }    finally  {      await  reader.close();    }  

}    async  function  writeStockInfos()  {  

 var  writer  =  new  AsyncFileWriter(“stocksAndPrices.txt”);    try  {        

     

 }    finally  {      await  writer.close();    }  

}  

   await  getStocks.forEach(async  function(name)  {        var  price  =  await  getStockPrice(name);        await  writer.writeLine(JSON.stringify({name,  price}));      });  

   for(var  name  on  getStocks())  {        var  price  =  await  getStockPrice(name);        await  writer.writeLine(JSON.stringify({name,  price}));      }  

promise returned from async next fn

Page 113: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Async IO with async function* async  function*  getStocks()  {  

 var  reader  =  new  AsyncFileReader(“stocks.txt”);    try  {        while(!reader.eof)  {        var  line  =  await  reader.readLine();        await  yield  JSON.parse(line);  

                   }    }    finally  {      await  reader.close();    }  

}    async  function  writeStockInfos()  {  

 var  writer  =  new  AsyncFileWriter(“stocksAndPrices.txt”);    try  {        

     

 }    finally  {      await  writer.close();    }  

}  

   await  getStocks.forEach(async  function(name)  {        var  price  =  await  getStockPrice(name);        await  writer.writeLine(JSON.stringify({name,  price}));      });  

promise returned from async next fn

Page 114: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Function Types in ES7

Synchronous Asynchronous

function T Promise

function* Iterator Observable

Page 115: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

More Info on async function*

Page 116: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

async function*

Page 117: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

ES Maturity Stage 0: Strawman

“Allow  for  feedback”  

Page 118: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Resources

•  esdiscuss.org •  https://facebook.github.io/regenerator/ •  http://taskjs.org/ •  http://github.com/jhusain/asyncgenerator

Page 119: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Questions?

?

Page 120: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Observer Pattern with Events

>  document.addEventListener(          “mousemove”,          function  next(e)  {            console.log(e);          });  

>  {  clientX:  425,  clientY:  543  }      

>  {  clientX:  450,  clientY:  558  }      

>  {  clientX:  455,  clientY:  562  }      

>  {  clientX:  460,  clientY:  743  }      

>  {  clientX:  476,  clientY:  760  }      

>  {  clientX:  476,  clientY:  760  }      

>  {  clientX:  476,  clientY:  760  }      

>  {  clientX:  476,  clientY:  760  }      

Page 121: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Observer Pattern with setInterval

>  var  counter  =  0;      setInterval(function  next(e)  {            console.log(counter++);      },  20);  

>  0      

>  1      

>  2      

>  3      

>  4  >  5  >  6  >  7  

Page 122: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

The decision to push or pull is orthogonal to most algorithms.

push

pull

Page 123: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iteration is Pull

var  result  =  generator.next();  

pull

Page 124: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Observation is Push

b  

generator.next(5);  

push

Page 125: ES7 - QCon New York · Server-sent Events Node Streams Service Workers jQuery Events XMLHttpRequest setInterval Observable . Implementing Observable WebSocket.prototype.observer=function(generator)

Iteration and Observation

are symmetrical