Async JavaScript in ES7 Modern Web UI Meetup http://www.modernwebui.org 5/13/2015 @ Mozilla HQ
Aug 06, 2015
Async JavaScript in ES7 Modern Web UI Meetup
http://www.modernwebui.org 5/13/2015 @ Mozilla HQ
Who is Mike North?
2 @MichaelLNorth
UI Engineering Lead
@MichaelLNorthgithub.com/truenorth
Blocking vs. Waiting
3
▪ Some people think of this as “push” vs “pull”
@MichaelLNorth
var weather = getForecast();
getForecast(function (weather) { ... });
▪ Blocking
▪ Waiting
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};}
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));}
Async - Callbacks
6 @MichaelLNorth
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
};})
})}
Some cool stuff coming in 2016that you can use right now
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}
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);}
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
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);
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
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();
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}
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}
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}
@MichaelLNorth18
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);}
};});
}
@MichaelLNorth20
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));
@MichaelLNorth21
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
@MichaelLNorth22
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));
PromiseValue
@MichaelLNorth23
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
@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};
}
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;}
@MichaelLNorth
Learn More
26
Netflix JavaScript Talks - Version 7: The Evolution of JavaScript