ðŸŠī\zansh.in\js

Play with the controls to see how the code works. All code is present in the page, but some scrollback may be necessary to grok everything.

# cancelling promises

2 min read

Three ways of cancelling promises: Using Revokable functions, Promises, and AbortController.

# OneWaySwitch()

const { isOn, turnOff } = OneWaySwitch()
function OneWaySwitch() {
let on = true
return {
isOn: () => on,
turnOff: () => (on = false)
}
}

# makeRevocable()

const log = makeRevocable(console.log)
const revoke = log.revoke
const run = () => log('hello, world')
function makeRevocable(fn) {
let revoked = false
const revoke = () => (revoked = true)
const wrapper = (...args) => {
if (revoked) return
fn(...args)
}
wrapper.revoke = revoke
return wrapper
}

# hold()

const pause = () =>
hold(1).then(n =>
console.log(`took ${n} seconds`)
)
function hold(n) {
return new Promise(resolve =>
setTimeout(resolve, n * 1000, n)
)
}

# then(revokable)

const log = makeRevocable(console.log)
const revoke = log.revoke
function run() {
hold(1).then(() => {
log('hello, world')
})
}

# makePromise()

const Log = msg => () => console.log(msg)
const [promise, resolve, reject] =
makePromise()
promise
.then(Log('then'))
.catch(Log('catch'))
.finally(Log('finally'))
function makePromise() {
let resolve
let reject
const promise = new Promise((O, X) => {
resolve = O
reject = X
})
return [promise, resolve, reject]
}

# cancelSignal Promise

const [cancelSignal, cancel] =
makePromise()
const pause = () =>
Promise.all([
hold(3, cancelSignal).then(Log('1')),
hold(1, cancelSignal).then(Log('2')),
hold(2, cancelSignal).then(Log('3'))
])
.then(Log('hello, world 👋'))
.catch(console.log)
function hold(n, cancelSignal) {
return new Promise((O, X) => {
const id = setTimeout(O, n * 1000, n)
cancelSignal.then(() => {
clearTimeout(id)
X(new Error('Cancelled'))
})
})
}

# AbortController

const controller = new AbortController()
const cancel = () => controller.abort()
const { signal } = controller
const pause = () =>
Promise.all([
hold(3, signal).then(Log('1')),
hold(1, signal).then(Log('2')),
hold(2, signal).then(Log('3'))
])
.then(Log('hello, world 👋'))
.catch(console.log)
function hold(n, signal) {
return new Promise((O, X) => {
const id = setTimeout(O, n * 1000, n)
signal.addEventListener(
'abort',
() => {
clearTimeout(id)
X(new Error('Cancelled'))
},
{ once: true }
)
})
}

Google it:

ðŸŒļ AbortController 🌚 closures 🌷 console.log ðŸŒŧ destructuring assignment 🌞 expression statement ðŸŒđ functions are objects 💐 hoisting ðŸŒļ partial application 🌚 Promise 🌷 setTimeout ðŸŒŧ spread rest