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

Higher-Order Promises

Higher-Order Promises

A promise is a container you get immediately for a value you get eventually. But a promise is also a value itself, and you can pass it around and return it from functions. What cool things do we get from treating our promises this way?

Talk given at CodeMash 2019

Neal Lindsay

January 10, 2019
Tweet

More Decks by Neal Lindsay

Other Decks in Programming

Transcript

  1. fetch('/url') // promise "a" .then(r => r.json() // promise "d"

    (maybe) ) // promise "b" .then(v => console.log(v)) // promise "c"
  2. " '

  3. handler functions • are called once (at most) • are

    never called synchronously • only one is called if both are provided to a .then()
  4. const log = (v) => { console.log(v) return v }

    const errLog = (e) => { console.error(e) throw e }
  5. const logWith = (m) => (v) => { console.log(m, v)

    return v } const errLogWith = (m) => (e) => { console.error(m, e) throw e }
  6. const recoverWith = (v) => () => v fetch('/url') .then(r

    => r.json()) .catch(recoverWith({val: 1})) .then(doWhatever)
  7. new Promise( (resolve, reject) => { oldFunc((err, data) => {

    if (err) reject(err) resolve(data) }) } )
  8. const timeoutAfter = (ms) => new Promise((_, reject) => {

    setTimeout(() => { reject(Error( `Timed out after ${ms}` )) }, ms) })
  9. const modalQuery = async (q) => {...} Promise .all([ modalQuery('accept

    privacy policy?'), modalQuery('accept code of conduct?') ]) .then(createAccount)
  10. const lockify = (f) => { let lock = Promise.resolve()

    return (...params) => { const resultPromise = lock.then(() => f(...params)) lock = resultPromise.catch(() => 1) return resultPromise } }
  11. const modalQuery = lockify( async (q) => {...} } Promise

    .all([ modalQuery('accept privacy policy?'), modalQuery('accept code of conduct?') ]) .then(createAccount)
  12. const promiseCache = (f, options) => { // way too

    much stuff for a slide! } const cachedFetch = promiseCache(fetch) cachedFetch('url').then(something) // ...time passes cachedFetch('url').then(somethingElse)
  13. function retry (tries, f) { if (tries < 2) return

    f return (...params) => f(...params) .catch(() => retry(tries - 1, f)(...params) ) } persistentFetch = retry(3, fetch)
  14. // too big to show in a slide const c

    = makeCancelable() c(fetch(url)) .then(r => c(r.json())) .then(doSomething) // ...later c.cancel('never mind')
  15. const waitForever = () => new Promise() const firstGood =

    (ps) => { return Promise.race( ps.map(p => p.catch(waitForever) ) ) }
  16. const waitForever = () => new Promise() const firstGood =

    (ps) => { return Promise.race( ps.map(p => p.catch(waitForever) ) ) } // if they all fail... (
  17. const firstGood = (ps) => { return new Promise((resolve, reject)

    => { ps.forEach(p => p.then(resolve)) Promise.all(ps) .catch(e => Promise .all(ps.map(p => p.catch(() => 0))) .then(() => reject(e)) ) }) } // )