You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

96 lines
2.3 KiB
TypeScript

import Emittery from "emittery";
//needed to pass information on wether or not the promise has been aborted witout 'this'
class AbortableEmittery extends Emittery {
public aborted = false;
abort() {
this.aborted = true;
this.emit("abort");
}
}
export default class AbortablePromise<T> extends Promise<T | null> {
private emitter: AbortableEmittery;
constructor(
make_generator: (
await_or_abort: (
promise: Promise<any>,
on_abort: () => Promise<unknown>
) => Promise<unknown>
) => AsyncGenerator
) {
const emitter = new AbortableEmittery();
const await_or_abort = (
promise: Promise<any>,
on_abort: () => Promise<unknown>
) => {
return new Promise((resolve, reject) => {
let resolved = false;
emitter.on("abort", () => {
if (!resolved) {
on_abort();
resolve(null);
resolved = true;
}
});
promise
.then((result) => {
if (!resolved) {
resolve(result);
resolved = true;
}
})
.catch(reject);
});
};
super(async (resolve, reject) => {
let step_value;
const generator = make_generator(await_or_abort);
do {
if (emitter.aborted) {
resolve(null);
return;
}
step_value = await generator.next();
} while (!step_value.done);
resolve(step_value.value);
});
this.emitter = emitter;
}
abort() {
this.emitter.abort();
}
}
// const sleep = promisify((timeout: number, callback: (...args: any[]) => void) =>
// setTimeout(callback, timeout)
// );
// const a = new AbortablePromise(async function* () {
// yield await sleep(1000);
// console.log("awaited 100");
// yield await sleep(2000);
// console.log("awaited 200");
// yield await sleep(3000);
// console.log("awaited 300");
// });
// setTimeout(() => a.abort(), 1500);
// const b = new AbortablePromise(async function* (await_or_abort) {
// const ping = await deferedSpawn("ping", ["8.8.8.8"]);
// while (true) {
// console.log(
// await await_or_abort(ping.waitForNextData(), () => {
// ping.kill();
// })
// );
// yield;
// }
// });
// setTimeout(() => b.abort(), 5000);