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 }
    )
  })
}