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
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);
|