Skip to content

Instantly share code, notes, and snippets.

@dead-claudia
Created June 3, 2018 02:11
Show Gist options
  • Save dead-claudia/bac73c9c54871d37c03dc0270918a6e7 to your computer and use it in GitHub Desktop.
Save dead-claudia/bac73c9c54871d37c03dc0270918a6e7 to your computer and use it in GitHub Desktop.
Cancel token for invoke-parallel
// This holds all the real state
class CancelController {
constructor(init) {
this._canceled = false
this._token = undefined
this._promise = undefined
this._cancels = undefined
this._resolve = undefined
}
get isCanceled() {
return this._canceled
}
get token() {
return this._token || (this._token = new CancelToken(this))
}
cancel() {
if (!this._canceled) {
this._canceled = true
const cancels = this._cancels
if (this._resolve != null) this._resolve()
this._resolve = undefined
this._cancels = undefined
if (cancels != null) cancels.forEach(cancel => cancel())
}
}
cancelAsync() {
if (!this._canceled) {
this._canceled = true
const cancels = this._cancels
const p = Promise.resolve()
if (this._resolve != null) p.then(this._resolve)
if (cancels != null) p.then(() => cancels.forEach(cancel => cancel()))
this._resolve = undefined
this._cancels = undefined
}
}
}
// Proxy for the controller, to provide privacy. Not directly exposed.
class CancelToken {
constructor(ctrl) {
this._ = ctrl
}
get isCanceled() {
return this._._canceled
}
get promise() {
return this._._promise || (this._._promise = new Promise(resolve => {
if (!this._._canceled) this._._resolve = resolve
}))
}
throwIfCanceled() {
if (this._._canceled) throw new Cancel()
}
addCancel(func) {
if (this._._canceled) return
if (this._._cancels == null) this._._cancels = new Set()
this._._cancels.add(func)
}
removeCancel(func) {
if (this._._cancels != null) this._._cancels.remove(func)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment