Skip to content

Instantly share code, notes, and snippets.

@tomsaleeba
Created April 29, 2020 11:57
Show Gist options
  • Save tomsaleeba/79384652da2515607bec74e2f45b7e38 to your computer and use it in GitHub Desktop.
Save tomsaleeba/79384652da2515607bec74e2f45b7e38 to your computer and use it in GitHub Desktop.
A test to see if you can truly cancel JS promises. Spoiler: you can't.
// Question: does calling reject on a running promise cut it short?
// Answer: sort of. It returns to the caller early but it keep running behind
// the scenes. So more of a short-circuit than really being cancelled.
const printFrequency = 500
const printRounds = 10
const cancelPoint = 7
let someOtherState = 'untouched'
const { thePromise, cancel } = (function slowCancellablePromise() {
let cancel
const thePromise = new Promise((resolve, reject) => {
cancel = () => {
reject('cancelled')
}
let count = 1
function printAndWait() {
console.log('hello ' + count)
someOtherState = count
setTimeout(() => {
if (count++ >= printRounds) {
return resolve()
}
printAndWait()
}, printFrequency)
}
printAndWait()
})
return { thePromise, cancel }
})()
thePromise
.then(() => console.log('finished normally'))
.catch(err => console.error('finished with error: ' + err))
.finally(() => {
console.log(
`after promise has returned, someOtherState = ${someOtherState}`,
)
console.log('waiting until the promise has actually finished...')
setTimeout(() => {
console.log(
`after promise has actually finished, someOtherState = ${someOtherState}`,
)
}, printFrequency * (printRounds - cancelPoint))
})
console.log('waiting for a bit...')
setTimeout(() => {
console.log('cancelling promise')
cancel()
console.log('the promise should stop printing')
}, printFrequency * cancelPoint)
// the output:
// hello 1
// waiting for a bit...
// hello 2
// hello 3
// hello 4
// hello 5
// hello 6
// hello 7
// cancelling promise
// the promise should stop printing
// finished with error: cancelled
// after promise has returned, someOtherState = 7
// waiting until the promise has actually finished...
// hello 8
// hello 9
// hello 10
// after promise has actually finished, someOtherState = 10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment