On Github JSWorkshops / async
Async programming in JS is hard.
/* Pyramid of DOOM! */ try{ var url = "someU.data"; showIndicator("fadein", downloadData(url, function(data){ processData(rawData, function(data){ displayData(data, removeIndicator) }); }); }); }catch(e){ console.log("argh... screw this!"); throw e; }
photo by Alper Çuğun
var p1 = Promise.resolve("fulfilled!"); p1.then((msg) => console.log(msg)); // "fulfilled!" var p2 = Promise.reject("rejected!"); p2.then(undefined, (msg) => console.log(msg)); // "Rejected!" var p3 = new Promise((resolve, reject) => { if (condition) resolve(); if (otherCondition) reject(); throw new Error("Error!"); }); //fulfill, reject, catch p3.then(success, failure) .catch(recover);
var p = new Promise((resolve,reject)=>{ //I'm on vacation in July! if(new Date().getMonth() === 7){ reject(new Error("On vacation!")); } else { resolve("Yeah, do it!"); } }); p.then( successMsg => console.log(successMsg), rejectMsg => console.log(rejectMsg) );
function canIdoTheWork(date){ return (date.getMonth() === 7)? Promise.reject(new Error("On vacation!")) : Promise.resolve("Let's do this!"); } canIdoTheWork(new Date()).then( successMsg => console.log(successMsg), rejectMsg => console.log(rejectMsg) );
var barista = { skills: new Set(['Americano', 'Latte']), get mood() { return Math.round(Math.random()) }, makeCoffee(type = 'Americano') { if (!this.skills.has(type)) { return Promise.reject(new Error(`No ${type} for you!`)); } return new Promise((resolve, reject) => { // 1 second to make a coffee setTimeout(() => { // 1 second to make a coffee if(this.mood){ return resolve(`Here is your ${type}`); } reject(new Error("I quit!")); }, 1000); }); } }
var success = msg => console.log(msg, "thanks!"); var fail = err => console.log(err); //reject straight away! barista.makeCoffee("milkshake").then(undefined, fail); //Make me an Americano and a latte barista.makeCoffee() .then(() => barista.makeCoffee("Latte")) .then(success).catch(fail);
var car1 = new Car("one"), var car2 = new Car("two"), var car3 = new Car("three"), var carRace = [car1.drive(), car2.drive(), car3.drive()]; Promise.race(carRace).then(e => console.log(e)); Promise.all(carRace).then(data => console.log(data));
A zero arguments function that, when called:
// A zero arguments function that, when called: obj[Symbol.iterator] = function() { // Returns an object return { // has .next() method. next() { // that returns an object with: return { value: "", // value prop done: trueOrFalse, // done prop }; } }; };
Hard to represent lazy lists in JS.
function* myGenerator(){ yield 1; } var genObj = myGenerator();
Yield control of execution at this point.
function* myGenerator(){ yield 1; } var genObj = myGenerator(); var result = myGenerator.next(); //run! // result = Object { value: 1, done: false }
This looks familiar...
function* myGenerator(value){ yield 1; return value; } var genObj = myGenerator("hello there"); var result = genObj.next(); //run! // result = Object { value: 1, done: false } result = genObj.next(); //keep going! // result = Object { value: "hello there", done: true }
function* myGenerator(value){ let result = yield value; return result; } var genObj = myGenerator("hello there"); var value = genObj.next().value; //first run! genObj.next(value.toUpperCase()); console.log(genObj.next().value); // "HELLO THERE"
function* myGenerator(value){ let result = ""; try{ result = yield 1; } catch (err) { result = "recovered"; } return result; } var genObj = myGenerator("hello there"); var result = genObj.next().value; if(typeof result !== "string"){ result = genObj.throw(new TypeError("Expected a string")); } console.log(result.value); // "Recovered"
*terms and conditions apply.
fetch(url) .then(response => response.json()) .then(json => processJson) .catch(handleError) .then(moarThen) .catch(err => throw err)
async function getJSON(url){ let response = await fetch(url); let result; try{ let json = await response.json(); result = processJson(json); } catch (err) { result = attempToRecover(err); } return result; } getJSON(someURL) .then(showIt) .catch(handleError);
function* getURL(url){ //... } // Generator object - initializes closure let getFoo = getURL("/foo");
function* getURL(url){ let response = yield fetch(url); } // Generator object - initializes closure let getFoo = getURL("/foo"); let {value: promise} = getFoo.next();
function* getURL(url){ let response = yield fetch(url); return yield response.text(); } // "Generator" object; let getFoo = getURL("/foo"); // Prime the pump - run to first yield! let {value: promise} = getFoo.next(); promise .then(res => getFoo.next(res).value) .then(text => console.log(text));
promise .then(res => getFoo.next(res).value) .then(text => console.log(text)) .catch(err => getFoo.throw(error));
async(function* getJSON(url){ let response = yield fetch(url); let result; try{ let json = yield response.json(); result = processJson(json); } catch (err) { result = attempToRecover(err); } return result; });