Skip to content

Instantly share code, notes, and snippets.

@lgrahl
Last active July 31, 2018 19:00
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lgrahl/8658b3088339930a522938fb35a9bc25 to your computer and use it in GitHub Desktop.
Save lgrahl/8658b3088339930a522938fb35a9bc25 to your computer and use it in GitHub Desktop.
Cancellable Promises
function sleep(timeout) {
return new Promise((resolve) => {
setTimeout(() => {
console.log('timeout!');
resolve();
}, timeout);
});
}
class Future extends Promise {
constructor(executor) {
let resolve, reject;
super((resolve_, reject_) => {
resolve = resolve_;
reject = reject_;
if (executor) {
return executor(resolve_, reject_);
}
});
this._done = false;
this._resolve = resolve;
this._reject = reject;
}
get done() {
return this._done;
}
resolve(...args) {
this._done = true;
return this._resolve(...args);
}
reject(...args) {
this._done = true;
return this._reject(...args);
}
}
class TaskContext {
constructor() {
this.futures = [];
}
guard(promise) {
const future = new Future();
promise.then((...args) => {
if (!future.done) {
future.resolve(...args);
}
});
this.futures.push(future);
return future;
}
cancel() {
console.log('CANCELLING');
for (const future of this.futures) {
future.reject('cancelled');
}
}
}
const tc = new TaskContext();
async function task(nr, interval, stop) {
for (let i = 0; i < stop; ++i) {
await tc.guard(sleep(interval));
console.log(`T${nr}.${i + 1}`);
}
tc.cancel();
}
async function main() {
await Promise.all([
task('A', 1000, 20),
task('B', 2500, 3),
]);
}
main();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment