-
-
Save getify/aef532057da25f934ce23f21c50c8d40 to your computer and use it in GitHub Desktop.
trying to make race/all combinators for AbortController signals that aren't leaky
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class cancelToken { | |
constructor(controller = new AbortController()) { | |
this.controller = controller; | |
this.signal = controller.signal; | |
({ | |
pr: this.signal.pr, | |
rej: this.rej, | |
} = signalPromise(this.signal)); | |
this.signal.pr.catch(() => { | |
this.controller.abort(); | |
this.rej = this.signal = this.signal.pr = this.controller = null; | |
}); | |
} | |
abort() { | |
this.rej(); | |
} | |
} | |
function signalPromise(signal) { | |
if (signal.pr) { | |
return { | |
pr: signal.pr, | |
}; | |
} | |
var ret = {}; | |
ret.pr = new Promise((res,rej) => { | |
signal.addEventListener("abort",rej,false); | |
ret.rej = rej; | |
}); | |
ret.pr.cleanup = () => { | |
if (signal) { | |
signal.removeEventListener("abort",ret.rej,false); | |
signal = null; | |
} | |
if (ret) { | |
ret = ret.pr = ret.pr.cleanup = ret.rej = null; | |
} | |
}; | |
ret.pr.catch(ret.pr.cleanup); | |
return ret; | |
} | |
function signalRace(signals) { | |
var token = new cancelToken(); | |
var prs = signals.map(signal => signalPromise(signal).pr); | |
var cleanups = prs.map(pr => pr.cleanup); | |
Promise.race(prs).catch(() => { | |
if (token) { | |
token.abort(); | |
token = null; | |
} | |
if (cleanups) { | |
cleanups.forEach(fn => fn()); | |
cleanups = null; | |
} | |
}); | |
prs = null; | |
return token.signal; | |
} | |
function signalAll(signals) { | |
var token = new cancelToken(); | |
var prs = signals.map(signal => signalPromise(signal).pr); | |
var cleanups = prs.map(pr => pr.cleanup); | |
Promise.all( | |
prs.map(pr => pr.catch(e => e)) | |
).then(() => { | |
if (token) { | |
token.abort(); | |
token = null; | |
} | |
if (cleanups) { | |
cleanups.forEach(fn => fn()); | |
cleanups = null; | |
} | |
}); | |
prs = null; | |
return token.signal; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var a = new cancelToken(); | |
var b = new AbortController(); | |
var c = new AbortController(); | |
var d = new AbortController(); | |
var e = signalAll([a.signal,b.signal,c.signal,d.signal]); | |
e.pr.catch(() => { console.log("aborted!"); }); | |
c.abort(); | |
a.abort(); | |
b.abort(); | |
d.abort(); | |
// aborted! |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var a = new cancelToken(); | |
var b = new AbortController(); | |
var c = new AbortController(); | |
var d = new AbortController(); | |
var e = signalAll([a.signal,b.signal,c.signal,d.signal]); | |
e.pr.catch(() => { console.log("aborted!"); }); | |
b.abort(); | |
// aborted! |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment