Top Banner
PROMISES THE UNSUNG HEROES OF ASYNC IN JAVASCRIPT DEAN RADCLIFFE • OK GROW! @DEANIUSDEV
51

Promises - The Unsung Heroes ofJavaScript

Mar 22, 2017

Download

Software

Dean Radcliffe
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Promises - The Unsung Heroes ofJavaScript

PROMISESTHE UNSUNG HEROES OF ASYNC IN

JAVASCRIPTDEAN RADCLIFFE • OK GROW! •

@DEANIUSDEV

Page 2: Promises - The Unsung Heroes ofJavaScript

A SPORTING BET"I BET YOU $20 THE REDS

WON'T BEAT THE CUBS THIS SEASON..."

Page 3: Promises - The Unsung Heroes ofJavaScript

TWO PROMISES➢ Begin Season then Cubs Lose then Season Ends↩ I Pay You

➢ Begin Season then Season Ends↩ You Pay Me

Page 4: Promises - The Unsung Heroes ofJavaScript

TWO PROMISES➢ Begin Season then Cubs Lose // ^ What if we made the bet after a loss ? then Season Ends↩ I Pay You

➢ Begin Season then Season Ends↩ You Pay Me

Page 5: Promises - The Unsung Heroes ofJavaScript

PROMISES: EVENTS, AT ANY TIMEA Promise represents a point in time which is:▸ ASAP, if something has already happened

▸ ASAP the moment it happens

Page 6: Promises - The Unsung Heroes ofJavaScript

PROMISES: VALUES, AT ANY TIMEA Promise provides access to a value whether:

▸ It is already known▸ It is being computed in this turn of the Event Loop▸ It may be un-knowable (maybe use a TimeOut)

Page 7: Promises - The Unsung Heroes ofJavaScript

PROMISES: ONE OR MORE CONDITIONS & ACTIONSA Promise can represent an entire chain of events,

with branching possibilities.var firstStep = new Promise()var allSteps = firstStep .then(isReady => isReady || makeReady) .then(lastStep)Promise.await(allSteps)

Page 8: Promises - The Unsung Heroes ofJavaScript

OUR BET - MAKE IT SO➢ let ourBet = BeginSeason() .then(Promise.race(CubsLoseToReds(), SeasonEnds())) .then(cubsLose => cubsLose ? iPayYou : youPayMe) //.then(iPayYou, youPayMe)

▸ CubsLoseToReds and SeasonEnds return Promises▸ CubsLose should return truthy (such as the score),▸ SeasonEnds should return falsy, or throw or reject

Page 9: Promises - The Unsung Heroes ofJavaScript

UNSUNG HEROES OF ASYNC▸ Standard, explicit contract of behavior▸ A promise can resolve or reject

▸ Its state may change 1x from pending to fulfilled▸ p.then(youPayMe, iPayYou)

▸ Or: p.then((value)=>{}) .catch((err)=>{})

Page 10: Promises - The Unsung Heroes ofJavaScript

BACK ON THE CHAIN GANGEach step in a .then chain:

RETURNS A CUMULATIVE PROMISE FOR ALL BEFORE

➢ let chain = promise1 .then(promise2) .then(action1)

Page 11: Promises - The Unsung Heroes ofJavaScript

BACK ON THE CHAIN GANGEach step in a .then chain may:

RETURN A VALUE / RETURN A PROMISE FOR A NEW VALUE

➢ BeginSeasonLossless .then(CubsLoseToReds) // <-- a Promise .then(iPayYou)

Page 12: Promises - The Unsung Heroes ofJavaScript

BACK ON THE CHAIN GANGEach step in a .then chain may:

RAISE AN EXCEPTION / RETURN REJECTED PROMISE

➢ BeginSeasonLossless .then(Promise.race(CubsLoseToReds,TimeOutAtSeasonEnd)) .then(iPayYou) .catch(youPayMe)

Page 13: Promises - The Unsung Heroes ofJavaScript

EXCEPTIONS▸ An uncaught exception in a .then is OK!

▸ A catch at the end can handle errors for the whole chain

Page 14: Promises - The Unsung Heroes ofJavaScript

COMIC RELIEF CAT PICTURE

Page 15: Promises - The Unsung Heroes ofJavaScript

QUESTION: HOW DO THESE EVENTS BEHAVE ?If you add an event listener after an event has happened,

does it make a sound ?document.addEventListener("DOMContentLoaded") // vs.$(document).ready // vs.$(document).on("ready")

Page 16: Promises - The Unsung Heroes ofJavaScript

QUESTION: HOW DO THESE EVENTS BEHAVE ?If you add an event listener after an event has happened,

does it make a sound ?document.addEventListener("DOMContentLoaded") // vs.$(document).ready // <<-- only this one - like a Promise // vs.$(document).on("ready")

Page 17: Promises - The Unsung Heroes ofJavaScript

PROVIDED ITS LOADED, 1➢ DomContentLoadedPromise.then(function () { console.log('Im ready') });↩ Promise {[[PromiseStatus]]: "resolved"}-----Im ready

Page 18: Promises - The Unsung Heroes ofJavaScript

PROVIDED ITS LOADED, 2➢ DomContentLoadedPromise.then(function () { console.log('Im ready') });↩ Promise {[[PromiseStatus]]: "pending"}-----

Page 19: Promises - The Unsung Heroes ofJavaScript

PROVIDED ITS LOADED, 2..➢ DomContentLoadedPromise.then(function () { console.log('Im ready') });↩ Promise {[[PromiseStatus]]: "pending"}-----...

Page 20: Promises - The Unsung Heroes ofJavaScript

PROVIDED ITS LOADED, 3➢ DomContentLoadedPromise.then(function () { console.log('Im ready') });↩ Promise {[[PromiseStatus]]: "pending"}-----..._____Im ready

Page 21: Promises - The Unsung Heroes ofJavaScript

WHAT'S WRONG WITH CALLBACKS ?Implicit, not formalized standard of behavior:

1. Function that takes 2 arguments▸ first argument is an error▸ second argument is the result

▸ Never pass both▸ error should be instanceof Error

Page 22: Promises - The Unsung Heroes ofJavaScript

WHAT'S WRONG WITH CALLBACKS ?Implicit, not formalized standard of behavior (cont.)

1. Must never execute on the same tick of the event loop2. Must be passed as last argument to function

3. Return value is ignored4. Must not throw / must pass resulting errors

5. Must never be called more than once

Page 23: Promises - The Unsung Heroes ofJavaScript

WHAT'S WRONG WITH CALLBACKS ?▸ Burdensome to check & propogate errors correctly

function doAsyncStuff (cb) { try { doStuff1(function(err, value) { if (err) return cb(err); try { doStuff2(value, function(err, value2) { if (err) return cb(err); cb(null, value2); }); } catch (e) { cb(e); } }) } catch (e) { cb(e); }}

Page 24: Promises - The Unsung Heroes ofJavaScript

WHAT'S RIGHT WITH PROMISES ?BEAUTIFUL TO CHECK ERRORS, EXCEPTION OR ASYNC!

// Promises FTW !!function doAsyncStuff () { return doStuff1() .then(doStuff2) .catch(function(err){ /*...*/})}

Page 25: Promises - The Unsung Heroes ofJavaScript

THE EVENT LOOP (AKA TASK

QUEUE)

Page 26: Promises - The Unsung Heroes ofJavaScript

THE EVENT LOOP (AKA TASK QUEUE)

Page 27: Promises - The Unsung Heroes ofJavaScript

THE 2 WAYS OF CODING JS

Page 28: Promises - The Unsung Heroes ofJavaScript

PROMISES AND REACTIVITYKeep an upperCase var in sync with

a variable called lowerCase let lowerCase = new ReactiveVar let upperCase = new ReactiveVar

Page 29: Promises - The Unsung Heroes ofJavaScript

PROMISES AND REACTIVITYKeep an upperCase var in sync with

a variable called lowerCase let lowerCase = new ReactiveVar let upperCase = new ReactiveVar

Tracker.autorun(() => { let x = lowerCase.get() upperCase.set(x.toUpperCase()) })

Page 30: Promises - The Unsung Heroes ofJavaScript

PROMISES AND REACTIVITYKeep an upperCase var in sync with

a variable called lowerCaselowerCase.set(x).then((x) => { upperCase.set(x.toUpperCase())})

Page 31: Promises - The Unsung Heroes ofJavaScript

PATTERNRETURNING A PROMISE FROM

A METEOR METHOD

Page 32: Promises - The Unsung Heroes ofJavaScript

RETURNING A PROMISE FROM A METEOR METHODReturn a Promise from a Method

Return an Eventual Value from a Method

Page 33: Promises - The Unsung Heroes ofJavaScript

RETURNING A PROMISE FROM A METEOR METHODReturn a Promise from a Method

Return an Eventual Value from a MethodEventually return a value from a Method

Page 34: Promises - The Unsung Heroes ofJavaScript

RETURNING A PROMISE FROM A METHOD, 1Meteor.methods({ futureTime() { return Promise.await(

); }})

Page 35: Promises - The Unsung Heroes ofJavaScript

RETURNING A PROMISE FROM A METHOD, 2Meteor.methods({ futureTime() { return Promise.await(new Promise((resolve) => {

//some callback code which should call 'resolve'

})); }})

Page 36: Promises - The Unsung Heroes ofJavaScript

RETURNING A PROMISE FROM A METHOD, 3Meteor.methods({ futureTime() { return Promise.await(new Promise((resolve) => { setTimeout(() => { console.log("its the future now") resolve(new Date()) }, 5000) })); }})

Page 37: Promises - The Unsung Heroes ofJavaScript

RETURNING A PROMISE FROM A METHOD, 4Meteor.methods({ futureTime() { let actions = new Promise((resolve) => setTimeout(()=> resolve(new Date), 5000)) .then(logAndReturn) .catch(logAndReturn); return Promise.await(actions); }})

Page 38: Promises - The Unsung Heroes ofJavaScript

ASYNC SHEEP

Page 39: Promises - The Unsung Heroes ofJavaScript

CALLING A METHOD Meteor.promise("futureTime") .then(log)

Page 40: Promises - The Unsung Heroes ofJavaScript

CALLING A METHOD, NOW AND LATER➢ Promise.resolve(new Date) .then(log) .then(() => Meteor.promise("futureTime")) .then(log)--- Fri Sep 18 2015 22:11:26 GMT-0500 (CDT)↩ Promise {[[PromiseStatus]]: "pending"}---Fri Sep 18 2015 22:11:31 GMT-0500 (CDT)

Page 41: Promises - The Unsung Heroes ofJavaScript

CALLING A METHOD, FUNNILYPromise.resolve(new Date) .then(log) .then(() => "futureTime") .then(Meteor.promise) .then(log)--- Fri Sep 18 2015 22:11:46 GMT-0500 (CDT)↩ Promise {[[PromiseStatus]]: "pending",---Fri Sep 18 2015 22:11:51 GMT-0500 (CDT)

Page 42: Promises - The Unsung Heroes ofJavaScript

var ComicReliefCatPicture; // TODO fill in

Page 43: Promises - The Unsung Heroes ofJavaScript

PROMISES AND REACTIVITYokgrow:promise

A promise's resolution can invalidate a computation ?

Awwwwwww yeah !

Page 44: Promises - The Unsung Heroes ofJavaScript

DEFINE A HELPER AROUND A PROMISE<template name="example1Demo"> <input id="arg1" value="foo"/> <input id="arg2" value="bar"/> <textarea> {{meteorPromise "addWithSleep" "arg1" "arg2"}} </textarea></template>

Page 45: Promises - The Unsung Heroes ofJavaScript

RETURN A PROMISE FROM A HELPER// {{meteorPromise "addWithSleep" "arg1" "arg2"}}Template.example1Demo.helpers({ meteorPromise: function (methodName, part1, part2) { var template = Template.instance(), value1 = template[part1].get(), value2 = template[part2].get();

// want to - but cant do this ! return Meteor.callPromise(methodName, value1, value2); }});

Page 46: Promises - The Unsung Heroes ofJavaScript

RETURN A PROMISE FROM A HELPER// {{meteorPromise "addWithSleep" "arg1" "arg2"}}Template.example1Demo.helpers({ meteorPromise: ReactivePromise(theHelperFunction, {pending: "loading..."})});var theHelperFunction = function (methodName, part1, part2) { var template = Template.instance(), value1 = template[part1].get(), value2 = template[part2].get();

return Meteor.callPromise(methodName, value1, value2);}

Page 47: Promises - The Unsung Heroes ofJavaScript

TMTOWTDICALLBACKS, PROMISES, FIBERS,

REACTIVITY, AND ES6 GENERATORS ARE ALL WAYS TO BE ASYNC!

(YOU CAN ALWAYS CONVERT)

Page 48: Promises - The Unsung Heroes ofJavaScript

QUESTIONS ??

Page 49: Promises - The Unsung Heroes ofJavaScript

PROMISES Я AWESOME

Page 50: Promises - The Unsung Heroes ofJavaScript

PROMISES Я AWESOMEAND SO ARE YOU!

Page 51: Promises - The Unsung Heroes ofJavaScript

DEAN RADCLIFFE, OK GROW! @DEANIUSDEV