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

Async/Await in JavaScript, today!

Async/Await in JavaScript, today!

A quick overview of iterators and generators, leading up to how they allow you to write code for async iteration with a simple for loop

Mike North

May 13, 2015
Tweet

More Decks by Mike North

Other Decks in Programming

Transcript

  1. Blocking vs. Waiting 3 ▪ Some people think of this

    as “push” vs “pull” @MichaelLNorth var weather = getForecast(); getForecast(function (weather) { ... }); ▪ Blocking ▪ Waiting
  2. Sync - Blocking is easy 4 ▪ Code is simple

    ▪ Error handling with try/catch ▪ We only have one thread @MichaelLNorth function getForecast() { let temperature = getTemperatureData(); let humidity = getHumidityData(); return {temperature, humidity}; }
  3. Async - Callbacks 5 ▪ See: Node.js ▪ Increased complexity

    ▪ Explicit error handling @MichaelLNorth function getForecast(cb) { getTemperatureData( temperature => { getHumidityData( humidity => { cb({ temperature, humidity }); }, error => cb(error)); }, error => cb(error)); }
  4. Async - Promises 7 ▪ Better error handling model ▪

    Still doesn’t look like our “blocking” code ▪ Promise-ness leaks out everywhere @MichaelLNorth function getForecast() { return getTemperatureData(temperature => { getHumidityData(humidity => { return { temperature, humidity }; }) }) }
  5. Iterators - Data Producers 9 ▪ A convention that all

    ES6 Collections will implement @MichaelLNorth let it = getCollection()[Symbol.iterator](); it.next(); // {value: 64, done: false} it.next(); // {value: 68, done: false} it.next(); // {value: undefined, done: true}
  6. For-Of Loop 10 @MichaelLNorth let a = [1,2,3,4,5]; for (let

    y of a) { console.log(y); } let a = [1,2,3,4,5]; let it = a[Symbol.iterator](); for(var i = it.next(); !i.done; i = it.next()) { console.log(i.value); }
  7. Generators - fns that return many values 11 @MichaelLNorth function*

    getValues() { yield 64; yield 68; return 71; } var values = getValues(); values.next(); // {value: 64, done: false} values.next(); // {value: 68, done: false} values.next(); // {value: 71, done: true} ▪ Generators return an iterator
  8. Generators - fns that return many values 12 @MichaelLNorth function*

    getValues() { yield 64; yield 68; return 71; } ▪ execution suspends @ yield ▪ values can be passed into a generator function* getValues() { var x = yield 64; var y = yield 2*x; return 3*y; } it.next(31);
  9. Generators - fns that return many values 13 @MichaelLNorth function*

    getValues() { yield 64; yield 68; return 71; } ▪ execution suspends @ yield ▪ values can be passed into a generator function* getValues() { var x = yield 64; var y = yield 2*x; return 3*y; } it.next(31); ▪ can iterate infinitely
  10. Generators - fns that return many values 14 @MichaelLNorth function*

    getValues() { var x = yield 64; var y = yield 2*x; return 3*y; } var it = getValues();
  11. Generators - fns that return many values 15 @MichaelLNorth function*

    getValues() { var x = yield 64; var y = yield 2*x; return 3*y; } var it = getValues(); it.next(); > {value: 64, done: false}
  12. Generators - fns that return many values 16 @MichaelLNorth function*

    getValues() { var x = yield 64 6; var y = yield 2*x; return 3*y; } var it = getValues(); it.next(); > {value: 64, done: false} it.next(6); > {value: 12, done: false}
  13. Generators - fns that return many values 17 @MichaelLNorth function*

    getValues() { var x = yield 64 6; var y = yield 2*x 3; return 3*y; } var it = getValues(); it.next(); > {value: 64, done: false} it.next(6); > {value: 12, done: false} it.next(3); > {value: 9, done: true}
  14. Async Iteration 19 @MichaelLNorth function spawn(generator) { return new Promise((resolve,

    reject) => { var resultHandler = lastResult => { var {value, done} = generator.next(lastResult); if (!done) { value.then(resultHandler, reject); } else { accept(value); } }; }); }
  15. @MichaelLNorth 20 function spawn(generator) { return new Promise((resolve, reject) =>

    { var resultHandler = lastResult => { var {value, done} = generator.next(lastResult); if (!done) { value.then(resultHandler, reject); } else { accept(value); } }; }); } function* getWeather(zip) { var temperature = yield getTemperature(zip); var humidity = yield getHumidity(zip); return {temperature, humidity}; } spawn(getWeather(zip)).then(weather => console.log(weather));
  16. @MichaelLNorth 21 function spawn(generator) { return new Promise((resolve, reject) =>

    { var resultHandler = lastResult => { var {value, done} = generator.next(lastResult); if (!done) { value.then(resultHandler, reject); } else { accept(value); } }; }); } function* getWeather(zip) { var temperature = yield getTemperature(zip); var humidity = yield getHumidity(zip); return {temperature, humidity}; } spawn(getWeather(zip)).then(weather => console.log(weather)); Promise
  17. @MichaelLNorth 22 function spawn(generator) { return new Promise((resolve, reject) =>

    { var resultHandler = lastResult => { var {value, done} = generator.next(lastResult); if (!done) { value.then(resultHandler, reject); } else { accept(value); } }; }); } function* getWeather(zip) { var temperature = yield getTemperature(zip) 72; var humidity = yield getHumidity(zip); return {temperature, humidity}; } spawn(getWeather(zip)).then(weather => console.log(weather)); Promise Value
  18. @MichaelLNorth 23 function spawn(generator) { return new Promise((resolve, reject) =>

    { var resultHandler = lastResult => { var {value, done} = generator.next(lastResult); if (!done) { value.then(resultHandler, reject); } else { accept(value); } }; }); } function* getWeather(zip) { var temperature = yield getTemperature(zip) 72; var humidity = yield getHumidity(zip) 0.32; return {temperature, humidity}; } spawn(getWeather(zip)).then(weather => console.log(weather)); Value
  19. @MichaelLNorth But wait… 24 function* getWeather(zip) { var temperature =

    yield getTemperature(zip); var humidity = yield getHumidity(zip); return {temperature, humidity}; } async function getWeather(zip) { var temperature = await getTemperature(zip); var humidity = await getHumidity(zip); return {temperature, humidity}; } function getWeather(zip) { var temperature = getTemperature(zip); var humidity = getHumidity(zip); return {temperature, humidity}; }
  20. Use it today 25 @MichaelLNorth babel: { nonStandard: false, optional:

    [ 'es7.asyncFunctions' ] } regeneratorRuntime.wrap(function getValues$ (context) { while (1) switch (context.prev = context.next) { case 0: context.next = 2; return 1; case 2: context.next = 4; return 2; case 4: return context.abrupt("return", 31); case 5: case "end": return context.stop(); } }, ...); function *getValues() { yield 1; yield 2; return 31; }