The gist: by having a Promise adopt the state of a forever pending one, you can suspend its then
handlers chain.
Promise.pending = Promise.race.bind(Promise, [])
let cancel
new Promise(function(fulfill, reject) {
cancel = function() {fulfill(Promise.pending())}
setTimeout(fulfill, 1000, 5)
}).then(console.log)
cancel() // 5 is never logged.
Also, mid-chain:
someAsyncJob().then(result => {
if (result === 'enough') return Promise.pending()
return moreAsyncWork()
}).then(otherResult => {
// won't run if result was 'enough'
})
Taking a page fron Bluebird (but without canceling parents up the chain)
function cancellablePromise(executor) {
let cancel
var res = new Promise(function(fulfill, reject) {
let handler
function onCancel(cb) {handler = cb}
cancel = function cancel() {
fulfill(Promise.pending()) // adopt a forever pending state
if (typeof handler === 'function') handler()
}
executor(fulfill, reject, onCancel)
})
res.cancel = cancel
return res
}
Alternatively
function cancellablePromise(executor) {
return new Promise(function(fulfill, reject) {
function cancel() {fulfill(Promise.pending())}
executor(fulfill, reject, cancel)
})
}
Given all the hubub around cancellable promises, I'm sure I'm missing something...
(Updated on 04/26/2023)
Here is my attempt:
So it can be implemented like this:
And output is:
Timeout 1 was aborted.
Timeout 1
.finally()
runs even if the timeout is aborted.Timeout 2 was aborted.
Timeout 3 completed after 3 seconds.
Timeout 4, which uses the same AbortController than timeout 1, was aborted.
Here the same AbortController can abort multiple promises
Typescript syntax:
Link to see it in action:
https://stackblitz.com/edit/promise-timeout-n-abort?file=index.js