Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Music City Code: ES7 and Beyond!

Music City Code: ES7 and Beyond!

This talks dives into some of the new (and experimental) features coming to ES7 and possibly later versions of JavaScript.

Jeremy Fairbank

August 29, 2015
Tweet

More Decks by Jeremy Fairbank

Other Decks in Programming

Transcript

  1. ES7

  2. Transpilers • Convert ES6/ES7/ES.later code into equivalent ES5 code. •

    Babel • babeljs.io • Traceur • github.com/google/traceur-compiler
  3. TC39 Process • Five stage process for converting an idea

    to a standard feature. • https://tc39.github.io/process-document
  4. Stage 0 - Strawman • Informal idea or proposal for

    change or addition. • Function bind operator 
 • Do expressions foo::bar(); let y = do { let x = 40; x + 2; }
  5. Stage 1 - Proposal • Make a case for addition

    by describing use cases, challenges, high-level API. • Class and property decorators class Foo { @memoize bar() { return 42; } }
  6. Stage 2 - Draft • Precise syntax and semantics; initial

    spec. • Object rest and spread properties
 • Async functions
 async function loadOrders() { const orders = await fetchJson('/orders'); console.log(orders); } let obj = { ...otherObj, x: 'foo' };
  7. Stage 3 - Candidate • Completed spec; needs reviewing for

    refinements. • Exponentiation operator
 • Array.prototype.includes 3 ** 2; // 9 [1, 2, 3].includes(2); // true
  8. Stage 4 - Finished • Ready to be included in

    the next ES standard. • No proposals at Stage 4 at the moment.
  9. Function Bind Operator • Binary and unary double colon ::

    operator • Bind this context to a function, by desugaring to bind, call, or apply. • https://github.com/zenparsing/es-function-bind • http://blog.jeremyfairbank.com/javascript/ javascript-es7-function-bind-syntax/
  10. Call Syntax function logThis() { console.log(this); } const obj =

    { foo: 'bar' }; logThis.call(obj); // { foo: 'bar' } // Now obj::logThis(); // { foo: 'bar' }
  11. Call Syntax function logThis() { console.log(this); } const obj =

    { foo: 'bar' }; logThis.call(obj); // { foo: 'bar' } // Now obj::logThis(); // { foo: 'bar' } Normal invocations would log window or the global object.
  12. Call Syntax function logThis() { console.log(this); } const obj =

    { foo: 'bar' }; logThis.call(obj); // { foo: 'bar' } // Now obj::logThis(); // { foo: 'bar' }
  13. Call Syntax function logThis() { console.log(this); } const obj =

    { foo: 'bar' }; logThis.call(obj); // { foo: 'bar' } // Now obj::logThis(); // { foo: 'bar' }
  14. function logThis(...args) { console.log(this, ...args); } function logObj1(obj, ...args) {

    logThis.apply(obj, args); } function logObj2(obj, ...args) { obj::logThis(...args); } const obj = { foo: 'bar' }; logObj1(obj, 42, 'baz'); // { foo: 'bar' } 42 'baz' logObj2(obj, 42, 'baz'); // { foo: 'bar' } 42 'baz' Apply Syntax
  15. Apply Syntax function logThis(...args) { console.log(this, ...args); } function logObj1(obj,

    ...args) { logThis.apply(obj, args); } function logObj2(obj, ...args) { obj::logThis(...args); } const obj = { foo: 'bar' }; logObj1(obj, 42, 'baz'); // { foo: 'bar' } 42 'baz' logObj2(obj, 42, 'baz'); // { foo: 'bar' } 42 'baz'
  16. Apply Syntax function logThis(...args) { console.log(this, ...args); } function logObj1(obj,

    ...args) { logThis.apply(obj, args); } function logObj2(obj, ...args) { obj::logThis(...args); } const obj = { foo: 'bar' }; logObj1(obj, 42, 'baz'); // { foo: 'bar' } 42 'baz' logObj2(obj, 42, 'baz'); // { foo: 'bar' } 42 'baz'
  17. Bind Syntax function logThis() { console.log(this); } const obj =

    { foo: 'bar' }; const logObj1 = logThis.bind(obj); logObj1(); // { foo: 'bar' } // Now const logObj2 = obj::logThis; logObj2(); // { foo: 'bar' }
  18. Bind Syntax function logThis() { console.log(this); } const obj =

    { foo: 'bar' }; const logObj1 = logThis.bind(obj); logObj1(); // { foo: 'bar' } // Now const logObj2 = obj::logThis; logObj2(); // { foo: 'bar' }
  19. Bind Syntax No parens, so bind instead of calling. function

    logThis() { console.log(this); } const obj = { foo: 'bar' }; const logObj1 = logThis.bind(obj); logObj1(); // { foo: 'bar' } // Now const logObj2 = obj::logThis; logObj2(); // { foo: 'bar' }
  20. Explicit vs. Implicit Bind const obj = { foo: 'bar',

    log() { console.log(this.foo); } }; const unbound = obj.log; const implicitBind = ::obj.log; const explicitBind = obj::obj.log; unbound(); // undefined implicitBind(); // bar explicitBind(); // bar
  21. const obj = { foo: 'bar', log() { console.log(this.foo); }

    }; const unbound = obj.log; const implicitBind = ::obj.log; const explicitBind = obj::obj.log; unbound(); // undefined implicitBind(); // bar explicitBind(); // bar Explicit vs. Implicit Bind Lose this context
  22. Explicit vs. Implicit Bind const obj = { foo: 'bar',

    log() { console.log(this.foo); } }; const unbound = obj.log; const implicitBind = ::obj.log; const explicitBind = obj::obj.log; unbound(); // undefined implicitBind(); // bar explicitBind(); // bar Implicitly bind to obj with unary operator.
  23. Explicit vs. Implicit Bind const obj = { foo: 'bar',

    log() { console.log(this.foo); } }; const unbound = obj.log; const implicitBind = ::obj.log; const explicitBind = obj::obj.log; unbound(); // undefined implicitBind(); // bar explicitBind(); // bar Explicitly bind to obj with binary operator.
  24. Why Function Bind Operator? • Succinct syntax for call, apply,

    and bind. • Virtual methods • Use array methods on DOM node lists. • Object method chaining with real methods and third party libs like Trine. • https://github.com/jussi-kalliokoski/trine • Callbacks to other libraries.
  25. Do Expressions • Make a block an expression. • Last

    statement in the block is the “return” value. • Prepend do keyword to a block to create. • Like syntactical sugar for IIFE. • http://wiki.ecmascript.org/doku.php?id=strawman:do_expressions
  26. Do Expressions const foo = do { const x =

    'b'; const y = 'a'; const z = 'r'; x + y + z; }; console.log(foo); // bar console.log(do { const x = 21; x * 2; }); // 42
  27. Do Expressions const foo = do { const x =

    'b'; const y = 'a'; const z = 'r'; x + y + z; }; console.log(foo); // bar console.log(do { const x = 21; x * 2; }); // 42 Locally scoped variables.
  28. Do Expressions const foo = do { const x =

    'b'; const y = 'a'; const z = 'r'; x + y + z; }; console.log(foo); // bar console.log(do { const x = 21; x * 2; }); // 42 Last statement is return value.
  29. Do Expressions const foo = do { const x =

    'b'; const y = 'a'; const z = 'r'; x + y + z; }; console.log(foo); // bar console.log(do { const x = 21; x * 2; }); // 42
  30. Ternary Alternative function readyResponse(ready) { const response = do {

    if (ready) "I'm ready. Let's go!"; else "Hold on a minute."; }; console.log(response); } readyResponse(true); // I'm ready. Let's go! readyResponse(false); // Hold on a minute.
  31. Ternary Alternative function readyResponse(ready) { const response = do {

    if (ready) "I'm ready. Let's go!"; else "Hold on a minute."; }; console.log(response); } readyResponse(true); // I'm ready. Let's go! readyResponse(false); // Hold on a minute. Each branch ends with an expression.
  32. Ternary Alternative const response = ready ? "I'm ready. Let's

    go!" : "Hold on a minute."; const response = do { if (ready) "I'm ready. Let's go!"; else "Hold on a minute."; }; Transpile
  33. Class Decorators • Annotate and modify classes and their properties.

    • Use @ and an expression that evaluates to a function. • Decorator precedes a class or method definition. • https://github.com/wycats/javascript-decorators
  34. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } get fullName() { return `${this.firstName} ${this.lastName}`; } } const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank
  35. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } get fullName() { return `${this.firstName} ${this.lastName}`; } } const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank
  36. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } get fullName() { return `${this.firstName} ${this.lastName}`; } } const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank Consequence: getters are nonenumerable by default.
  37. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } } Object.defineProperty(Person.prototype, 'fullName', { enumerable: true, get() { return `${this.firstName} ${this.lastName}`; } }); const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank // fullName: Jeremy Fairbank
  38. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } } Object.defineProperty(Person.prototype, 'fullName', { enumerable: true, get() { return `${this.firstName} ${this.lastName}`; } }); const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank // fullName: Jeremy Fairbank
  39. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } } Object.defineProperty(Person.prototype, 'fullName', { enumerable: true, get() { return `${this.firstName} ${this.lastName}`; } }); const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank // fullName: Jeremy Fairbank
  40. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } @enumerable get fullName() { return `${this.firstName} ${this.lastName}`; } } const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank // fullName: Jeremy Fairbank
  41. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } @enumerable get fullName() { return `${this.firstName} ${this.lastName}`; } } const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank // fullName: Jeremy Fairbank
  42. class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName

    = lastName; } @enumerable get fullName() { return `${this.firstName} ${this.lastName}`; } } const p = new Person('Jeremy', 'Fairbank'); for (const key in p) { console.log(`${key}: ${p[key]}`); } // firstName: Jeremy // lastName: Fairbank // fullName: Jeremy Fairbank
  43. function enumerable(target, name, descriptor) { descriptor.enumerable = true; return descriptor;

    } Just Functions Object being modified (e.g. prototype or a class based on usage)
  44. function enumerable(target, name, descriptor) { descriptor.enumerable = true; return descriptor;

    } Just Functions Name of property that will be added to target
  45. function enumerable(target, name, descriptor) { descriptor.enumerable = true; return descriptor;

    } Just Functions Object literal defining the property that will be added to target
  46. function enumerable(target, name, descriptor) { descriptor.enumerable = true; return descriptor;

    } Just Functions Return is optional if you mutate descriptor. Useful if you want to create new descriptor.
  47. Just Functions @enumerable get fullName() { return `${this.firstName} ${this.lastName}`; }

    let descriptor = { get() { return `${this.firstName} ${this.lastName}`; }, enumerable: false, configurable: true }; descriptor = enumerable(Person.prototype, 'fullName', descriptor) || descriptor; Object.defineProperty(Person.prototype, 'fullName', descriptor);
  48. Just Functions @enumerable get fullName() { return `${this.firstName} ${this.lastName}`; }

    let descriptor = { get() { return `${this.firstName} ${this.lastName}`; }, enumerable: false, configurable: true }; descriptor = enumerable(Person.prototype, 'fullName', descriptor) || descriptor; Object.defineProperty(Person.prototype, 'fullName', descriptor);
  49. Just Functions @enumerable get fullName() { return `${this.firstName} ${this.lastName}`; }

    let descriptor = { get() { return `${this.firstName} ${this.lastName}`; }, enumerable: false, configurable: true }; descriptor = enumerable(Person.prototype, 'fullName', descriptor) || descriptor; Object.defineProperty(Person.prototype, 'fullName', descriptor);
  50. Just Functions @enumerable get fullName() { return `${this.firstName} ${this.lastName}`; }

    let descriptor = { get() { return `${this.firstName} ${this.lastName}`; }, enumerable: false, configurable: true }; descriptor = enumerable(Person.prototype, 'fullName', descriptor) || descriptor; Object.defineProperty(Person.prototype, 'fullName', descriptor);
  51. Decorators and Arguments class Person { constructor(name) { this.name =

    name; } @alias('sayHello') greet() { console.log(`Hello. My name is ${this.name}.`); } } const person = new Person('Jeremy'); person.greet(); // Hello. My name is Jeremy. person.sayHello(); // Hello. My name is Jeremy.
  52. Decorators and Arguments class Person { constructor(name) { this.name =

    name; } @alias('sayHello') greet() { console.log(`Hello. My name is ${this.name}.`); } } const person = new Person('Jeremy'); person.greet(); // Hello. My name is Jeremy. person.sayHello(); // Hello. My name is Jeremy. Evaluate function call and use return value as decorator.
  53. Decorators and Arguments class Person { constructor(name) { this.name =

    name; } @alias('sayHello') greet() { console.log(`Hello. My name is ${this.name}.`); } } const person = new Person('Jeremy'); person.greet(); // Hello. My name is Jeremy. person.sayHello(); // Hello. My name is Jeremy.
  54. Decorators with Parameters function alias(aliasName) { return (target, name, descriptor)

    => { const newDescriptor = Object.assign({}, descriptor, { value(...args) { return this[name](...args); } }); Object.defineProperty(target, aliasName, newDescriptor); }; }
  55. Decorators with Parameters function alias(aliasName) { return (target, name, descriptor)

    => { const newDescriptor = Object.assign({}, descriptor, { value(...args) { return this[name](...args); } }); Object.defineProperty(target, aliasName, newDescriptor); }; } Take a parameter
  56. Decorators with Parameters function alias(aliasName) { return (target, name, descriptor)

    => { const newDescriptor = Object.assign({}, descriptor, { value(...args) { return this[name](...args); } }); Object.defineProperty(target, aliasName, newDescriptor); }; } Actual decorator function
  57. const Quadrupedal = { walk() { console.log(`${this.name} walks with four

    legs`); } }; @mixin(Quadrupedal, EventEmitter.prototype) class Dog { constructor(name, age) { this.name = name; this.age = age; } haveBirthday() { this.age++; this.emit('birthday', this); } }
  58. const Quadrupedal = { walk() { console.log(`${this.name} walks with four

    legs`); } }; @mixin(Quadrupedal, EventEmitter.prototype) class Dog { constructor(name, age) { this.name = name; this.age = age; } haveBirthday() { this.age++; this.emit('birthday', this); } } Use a decorator on the class
  59. const Quadrupedal = { walk() { console.log(`${this.name} walks with four

    legs`); } }; @mixin(Quadrupedal, EventEmitter.prototype) class Dog { constructor(name, age) { this.name = name; this.age = age; } haveBirthday() { this.age++; this.emit('birthday', this); } }
  60. const dog = new Dog('Tucker', 8); dog.on('birthday', d => {

    console.log(`${d.name} just turned ${d.age}`); }); dog.haveBirthday(); // Tucker just turned 9 dog.walk(); // Tucker walks with four legs
  61. const dog = new Dog('Tucker', 8); dog.on('birthday', d => {

    console.log(`${d.name} just turned ${d.age}`); }); dog.haveBirthday(); // Tucker just turned 9 dog.walk(); // Tucker walks with four legs From EventEmitter From Quadrupedal
  62. Why Class Decorators? • Extremely powerful and expressive syntax for

    class/property modification. • Mixins — no more fragile base class or multiple inheritance issues. • @autobind, @deprecate, @memoize, @readonly, and more! • https://github.com/jayphelps/core-decorators.js
  63. Async Functions • Provide synchronous-like syntax for asynchronous code. •

    Prepend function with async. • Use await operator on a promise to obtain a fulfilled promise value. • https://github.com/tc39/ecmascript-asyncawait
  64. function loadOrder(orderId) { fetchJson(`/orders/${orderId}`) .then(order => console.log(order)); } async function

    loadOrder(orderId) { const order = await fetchJson(`/orders/${orderId}`); console.log(order); } loadOrder(1);
  65. async function loadOrder(orderId) { const order = await fetchJson(`/orders/${orderId}`); console.log(order);

    } loadOrder(1); Await a promise and obtain the fulfilled/resolved value. Nonblocking.
  66. Wrap awaited expression in Promise. async function loadOrder(orderId) { const

    promise = Promise.resolve( fetchJson(`/orders/${orderId}`) ); console.log(order); } loadOrder(1);
  67. Wrap remaining code in a then callback. async function loadOrder(orderId)

    { const promise = Promise.resolve( fetchJson(`/orders/${orderId}`) ); console.log(order); } loadOrder(1);
  68. Wrap remaining code in a then callback. function loadOrder(orderId) {

    const promise = Promise.resolve( fetchJson(`/orders/${orderId}`) ); return promise.then(order => { console.log(order); return Promise.resolve(undefined); }); } loadOrder(1);
  69. No explicit return, so return a resolved undefined value. function

    loadOrder(orderId) { const promise = Promise.resolve( fetchJson(`/orders/${orderId}`) ); return promise.then(order => { console.log(order); return Promise.resolve(undefined); }); } loadOrder(1);
  70. async function loadOrder(orderId) { const order = await fetchJson(`/orders/${orderId}`); console.log(order);

    } function loadOrder(orderId) { const promise = Promise.resolve( fetchJson(`/orders/${orderId}`) ); return promise.then(order => { console.log(order); return Promise.resolve(undefined); }); } Final equivalent-ish code
  71. async function loadOrder(orderId) { const order = await fetchJson(`/orders/${orderId}`); console.log(order);

    } function loadOrder(orderId) { const promise = Promise.resolve( fetchJson(`/orders/${orderId}`) ); return promise.then(order => { console.log(order); return Promise.resolve(undefined); }); } What does this function look like?
  72. Multiple Awaits async function fetchJson(url) { const resp = await

    fetch(url); const data = await resp.json(); const isSuccess = resp.status >= 200 && resp.status < 300; if (isSuccess) { return data; } const error = new Error(resp.responseText); error.data = data; throw error; }
  73. Multiple Awaits async function fetchJson(url) { const resp = await

    fetch(url); const data = await resp.json(); const isSuccess = resp.status >= 200 && resp.status < 300; if (isSuccess) { return data; } const error = new Error(resp.responseText); error.data = data; throw error; } Potential for dependency means sequential awaits are NOT parallel!
  74. Multiple Awaits async function fetchJson(url) { const resp = await

    fetch(url); const data = await resp.json(); const isSuccess = resp.status >= 200 && resp.status < 300; if (isSuccess) { return data; } const error = new Error(resp.responseText); error.data = data; throw error; }
  75. Multiple Awaits async function fetchJson(url) { const resp = await

    fetch(url); const data = await resp.json(); const isSuccess = resp.status >= 200 && resp.status < 300; if (isSuccess) { return data; } const error = new Error(resp.responseText); error.data = data; throw error; } What will happen?
  76. Error Handling async function loadOrder(orderId) { try { const order

    = await fetchJson(`/orders/${orderId}`); console.log(order); } catch(e) { console.log('error retrieving order', e.data); } } loadOrder(1);
  77. Error Handling async function loadOrder(orderId) { try { const order

    = await fetchJson(`/orders/${orderId}`); console.log(order); } catch(e) { console.log('error retrieving order', e.data); } } loadOrder(1); Promise was resolved
  78. Error Handling async function loadOrder(orderId) { try { const order

    = await fetchJson(`/orders/${orderId}`); console.log(order); } catch(e) { console.log('error retrieving order', e.data); } } loadOrder(1); Promise was rejected
  79. function loadOrder(orderId) { fetchJson(`/orders/${orderId}`) .then(order => console.log(order)) .catch(e => console.log('error

    retrieving order', e.data)); } async function loadOrder(orderId) { try { const order = await fetchJson(`/orders/${orderId}`); console.log(order); } catch(e) { console.log('error retrieving order', e.data); } }
  80. function loadOrder(orderId) { fetchJson(`/orders/${orderId}`) .then(order => console.log(order)) .catch(e => console.log('error

    retrieving order', e.data)); } async function loadOrder(orderId) { try { const order = await fetchJson(`/orders/${orderId}`); console.log(order); } catch(e) { console.log('error retrieving order', e.data); } }
  81. function loadOrder(orderId) { fetchJson(`/orders/${orderId}`) .then(order => console.log(order)) .catch(e => console.log('error

    retrieving order', e.data)); } async function loadOrder(orderId) { try { const order = await fetchJson(`/orders/${orderId}`); console.log(order); } catch(e) { console.log('error retrieving order', e.data); } }
  82. function loadOrder(orderId) { fetchJson(`/orders/${orderId}`) .then(order => console.log(order)) .catch(e => console.log('error

    retrieving order', e.data)); } async function loadOrder(orderId) { try { const order = await fetchJson(`/orders/${orderId}`); console.log(order); } catch(e) { console.log('error retrieving order', e.data); } }
  83. Explicit Returns async function life() { return 42; } const

    answer = life(); What is the value of answer?
  84. Explicit Returns async function life() { return 42; } const

    answer = life(); assert(answer !== 42); assert(answer instanceof Promise); answer.then(value => assert(value === 42));
  85. Explicit Returns async function life() { return 42; } Remember

    that async functions wrap the return value with Promise.resolve. function life() { return Promise.resolve(42); }
  86. Sequential vs. Parallel async function loadOrders(orderIds) { const orders =

    []; for (const id of orderIds) { const order = await fetchJson(`/orders/${id}`); orders.push(order); } console.log(orders); } loadOrders([1, 2, 3]);
  87. Sequential vs. Parallel async function loadOrders(orderIds) { const orders =

    []; for (const id of orderIds) { const order = await fetchJson(`/orders/${id}`); orders.push(order); } console.log(orders); } loadOrders([1, 2, 3]); Each step of loop has to wait. Issue if requests aren’t dependent on each other.
  88. async function loadOrders(orderIds) { const orders = await Promise.all(orderIds.map(id =>

    { return fetchJson(`/orders/${id}`); })); console.log(orders); } loadOrders([1, 2, 3]); Sequential vs. Parallel
  89. Sequential vs. Parallel async function loadOrders(orderIds) { const orders =

    await Promise.all(orderIds.map(id => { return fetchJson(`/orders/${id}`); })); console.log(orders); } loadOrders([1, 2, 3]); Make all requests at once and resolve with Promise.all. Allows for parallelism.
  90. Sequential Queue Request /orders/1
 (wait: 0s) Requests Request /orders/2
 (wait:

    0s) Request /orders/3
 (wait: 0s) Finished Time Total: 0s
  91. Sequential Queue Requests Request /orders/3
 (wait: 0s) Finished Request /orders/1


    (wait: 0s) Time Total: 0s Request /orders/2
 (wait: 0s)
  92. Sequential Queue Requests Finished Request /orders/1
 (wait: 0s, resp: 1s)

    Time Total: 1s Request /orders/2
 (wait: 1s) Request /orders/3
 (wait: 1s)
  93. Sequential Queue Requests Finished Request /orders/1
 (wait: 0s, resp: 1s)

    Time Total: 1s Request /orders/2
 (wait: 1s) Request /orders/3
 (wait: 1s)
  94. Sequential Queue Requests Finished Request /orders/1
 (wait: 0s, resp: 1s)

    Time Total: 7s Request /orders/2
 (wait: 1s, resp: 6s) Request /orders/3
 (wait: 7s)
  95. Sequential Queue Requests Request /orders/3
 (wait: 7s) Finished Request /orders/1


    (wait: 0s, resp: 1s) Time Total: 7s Request /orders/2
 (wait: 1s, resp: 6s)
  96. Sequential Queue Requests Request /orders/3
 (wait: 7s, resp: 2s) Finished

    Request /orders/1
 (wait: 0s, resp: 1s) Time Total: 9s Request /orders/2
 (wait: 1s, resp: 6s)
  97. Sequential Queue Requests Request /orders/3
 (wait: 7s, resp: 2s) Finished

    Request /orders/1
 (wait: 0s, resp: 1s) Time Total: 9s Request /orders/2
 (wait: 1s, resp: 6s) Limited by response time of every request.
  98. Parallel Queue Request /orders/1
 (wait: 0s) Requests Request /orders/2
 (wait:

    0s) Request /orders/3
 (wait: 0s) Finished Time Total: 0s
  99. Parallel Queue Request /orders/1
 (wait: 0s) Requests Request /orders/2
 (wait:

    0s) Request /orders/3
 (wait: 0s) Finished Time Total: 0s
  100. Parallel Queue Request /orders/2
 (wait: 0s) Requests Request /orders/3
 (wait:

    0s) Finished Time Total: 1s Request /orders/1
 (wait: 0s, resp: 1s)
  101. Parallel Queue Request /orders/2
 (wait: 0s) Requests Request /orders/3
 (wait:

    0s, resp: 2s) Finished Time Total: 2s Request /orders/1
 (wait: 0s, resp: 1s)
  102. Parallel Queue Request /orders/2
 (wait: 0s, resp: 6s) Requests Request

    /orders/3
 (wait: 0s, resp: 2s) Finished Time Total: 6s Request /orders/1
 (wait: 0s, resp: 1s)
  103. Parallel Queue Request /orders/2
 (wait: 0s, resp: 6s) Requests Request

    /orders/3
 (wait: 0s, resp: 2s) Finished Time Total: 6s Request /orders/1
 (wait: 0s, resp: 1s) Limited by slowest request instead of every request.
  104. Why Async Functions? • Synchronous-looking asynchronous code. • Gain back

    use of native language flow control constructs with asynchronous code (e.g. for..of, try/catch).
  105. Other upcoming features • Stage 3: Exponentiation operator, Array.prototype.includes •

    Stage 2: Object.observe, SIMD • Stage 1: Object rest and spread properties, typed objects, Observable • Stage 0: Shared memory and atomics, class property initializers • Many more!
  106. Resources • https://github.com/tc39/ecma262 • http://babeljs.io/ • $ babel --stage 0

    myAwesomeES7code.js • https://tc39.github.io/process-document/ • https://esdiscuss.org/ • http://www.ecma-international.org/memento/ contribute_TC39_Royalty_Free_Task_Group.php