The gist: by having a Promise adopt the state of a forever pending one, you can suspend its then handlers chain.
const foreverPending = new Promise(function() {});
let cancel
new Promise(function(fulfill, reject) {
cancel = function() {fulfill(foreverPending)}
setTimeout(fulfill, 1000, 5)
}).then(console.log)
cancel() // 5 is never logged.
Also, mid-chain:
someAsyncJob().then(result => {
if (result === 'enough') return foreverPending
return moreAsyncWork()
}).then(otherResult => {
// won't run if result was 'enough'
})
Possible implementations/API:
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(foreverPending) // adopt a forever pending state
if (typeof handler === 'function') handler()
}
executor(fulfill, reject, onCancel)
})
res.cancel = cancel
return res
}
Alternatively
let foreverPending = new Promise(function() {});
function cancellablePromise(executor) {
return new Promise(function(fulfill, reject) {
function cancel() {fulfill(foreverPending)} // adopt a forever pending state
executor(fulfill, reject, cancel)
})
}
Given all the hubub around cancellable promises, I'm sure I'm missing something...