diff --git a/src/index.ts b/src/index.ts index 8020c9f..95f3bd4 100644 --- a/src/index.ts +++ b/src/index.ts @@ -14,7 +14,7 @@ class AbortableEmittery extends Emittery { export default class AbortablePromise implements Promise { private emitter: AbortableEmittery; - private result_promise: Promise; + private result_promise: Promise; private fulfilled = false; private result: T; @@ -33,7 +33,7 @@ export default class AbortablePromise implements Promise { function await_or_abort( promise: Promise | AbortablePromise, on_abort?: () => Promise | void - ): Promise { + ): Promise { console.log("await_or_abort", promise); if (promise instanceof AbortablePromise && !on_abort) { on_abort = async () => promise.abort(); @@ -86,6 +86,10 @@ export default class AbortablePromise implements Promise { this.emitter.abort(); } + get [Symbol.toStringTag]() { + return "AbortablePromise"; + } + then( onfulfilled?: | ((value: T) => TResult1 | PromiseLike) @@ -99,7 +103,7 @@ export default class AbortablePromise implements Promise { const self = this; return new AbortablePromise(async function* (await_or_abort) { if (self.fulfilled) { - onfulfilled(self.result); + onfulfilled && onfulfilled(self.result); return; } const ret = await await_or_abort(self.result_promise, () => { @@ -107,7 +111,7 @@ export default class AbortablePromise implements Promise { }); yield; if (onfulfilled) { - onfulfilled(ret); + onfulfilled(ret as T); } }); } @@ -127,13 +131,21 @@ export default class AbortablePromise implements Promise { }); } + finally(onfinally?: (() => void) | undefined | null): AbortablePromise { + const self = this; + return new AbortablePromise(async function* (await_or_abort) { + await await_or_abort(self); + onfinally && onfinally(); + }); + } + static deadlyRace( promises: AbortablePromise[], should_kill_others: (arg: L) => Promise = async () => true ): Promise { return new AbortablePromise(async function* (await_or_abort) { return await_or_abort( - new Promise((resolve, reject) => { + new Promise((resolve, _) => { let resolved = false; const callback = async (arg: L) => { if (resolved) return; @@ -156,55 +168,3 @@ export default class AbortablePromise implements Promise { }); } } - -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"); -// }); -// -// 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"); -// }); - -// function abortableSleep(ms: number): AbortablePromise { -// return new AbortablePromise(async function* () { -// await sleep(ms); -// yield; -// console.log(`Slept ${ms}.`); -// }); -// } - -// const b = AbortablePromise.deadlyRace([ -// abortableSleep(1000), -// abortableSleep(2000), -// abortableSleep(3000), -// ]); - -// 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); diff --git a/src/test.ts b/src/test.ts new file mode 100644 index 0000000..b3dd59b --- /dev/null +++ b/src/test.ts @@ -0,0 +1,45 @@ +import { promisify } from "util"; +import AbortablePromise from "."; + +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); + +function abortableSleep(ms: number): AbortablePromise { + return new AbortablePromise(async function* () { + await sleep(ms); + yield; + console.log(`Slept ${ms}.`); + }); +} + +const b = AbortablePromise.deadlyRace([ + abortableSleep(1000), + abortableSleep(2000), + abortableSleep(3000), +]); + +// 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);