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...
Why is
Promise.pending = Promise.race.bind(Promise, [])
? Couldn't it just bePromise.pending = new Promise(() => {/* never resolve or reject */});
? Doesn't the current implementation create a new Promise every time you cancel something?