|
|
@ -14,7 +14,7 @@ class AbortableEmittery extends Emittery {
|
|
|
|
export default class AbortablePromise<T> implements Promise<T | null> {
|
|
|
|
export default class AbortablePromise<T> implements Promise<T | null> {
|
|
|
|
private emitter: AbortableEmittery;
|
|
|
|
private emitter: AbortableEmittery;
|
|
|
|
|
|
|
|
|
|
|
|
private result_promise: Promise<T>;
|
|
|
|
private result_promise: Promise<T | null>;
|
|
|
|
private fulfilled = false;
|
|
|
|
private fulfilled = false;
|
|
|
|
private result: T;
|
|
|
|
private result: T;
|
|
|
|
|
|
|
|
|
|
|
@ -33,7 +33,7 @@ export default class AbortablePromise<T> implements Promise<T | null> {
|
|
|
|
function await_or_abort<L = any>(
|
|
|
|
function await_or_abort<L = any>(
|
|
|
|
promise: Promise<L> | AbortablePromise<L>,
|
|
|
|
promise: Promise<L> | AbortablePromise<L>,
|
|
|
|
on_abort?: () => Promise<unknown> | void
|
|
|
|
on_abort?: () => Promise<unknown> | void
|
|
|
|
): Promise<L> {
|
|
|
|
): Promise<L | null> {
|
|
|
|
console.log("await_or_abort", promise);
|
|
|
|
console.log("await_or_abort", promise);
|
|
|
|
if (promise instanceof AbortablePromise && !on_abort) {
|
|
|
|
if (promise instanceof AbortablePromise && !on_abort) {
|
|
|
|
on_abort = async () => promise.abort();
|
|
|
|
on_abort = async () => promise.abort();
|
|
|
@ -86,6 +86,10 @@ export default class AbortablePromise<T> implements Promise<T | null> {
|
|
|
|
this.emitter.abort();
|
|
|
|
this.emitter.abort();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
get [Symbol.toStringTag]() {
|
|
|
|
|
|
|
|
return "AbortablePromise";
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
then<TResult1 = T, TResult2 = never>(
|
|
|
|
then<TResult1 = T, TResult2 = never>(
|
|
|
|
onfulfilled?:
|
|
|
|
onfulfilled?:
|
|
|
|
| ((value: T) => TResult1 | PromiseLike<TResult1>)
|
|
|
|
| ((value: T) => TResult1 | PromiseLike<TResult1>)
|
|
|
@ -99,7 +103,7 @@ export default class AbortablePromise<T> implements Promise<T | null> {
|
|
|
|
const self = this;
|
|
|
|
const self = this;
|
|
|
|
return new AbortablePromise(async function* (await_or_abort) {
|
|
|
|
return new AbortablePromise(async function* (await_or_abort) {
|
|
|
|
if (self.fulfilled) {
|
|
|
|
if (self.fulfilled) {
|
|
|
|
onfulfilled(self.result);
|
|
|
|
onfulfilled && onfulfilled(self.result);
|
|
|
|
return;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const ret = await await_or_abort(self.result_promise, () => {
|
|
|
|
const ret = await await_or_abort(self.result_promise, () => {
|
|
|
@ -107,7 +111,7 @@ export default class AbortablePromise<T> implements Promise<T | null> {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
yield;
|
|
|
|
yield;
|
|
|
|
if (onfulfilled) {
|
|
|
|
if (onfulfilled) {
|
|
|
|
onfulfilled(ret);
|
|
|
|
onfulfilled(ret as T);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -127,13 +131,21 @@ export default class AbortablePromise<T> implements Promise<T | null> {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
finally(onfinally?: (() => void) | undefined | null): AbortablePromise<T> {
|
|
|
|
|
|
|
|
const self = this;
|
|
|
|
|
|
|
|
return new AbortablePromise(async function* (await_or_abort) {
|
|
|
|
|
|
|
|
await await_or_abort(self);
|
|
|
|
|
|
|
|
onfinally && onfinally();
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static deadlyRace<L>(
|
|
|
|
static deadlyRace<L>(
|
|
|
|
promises: AbortablePromise<L>[],
|
|
|
|
promises: AbortablePromise<L>[],
|
|
|
|
should_kill_others: (arg: L) => Promise<boolean> = async () => true
|
|
|
|
should_kill_others: (arg: L) => Promise<boolean> = async () => true
|
|
|
|
): Promise<L> {
|
|
|
|
): Promise<L> {
|
|
|
|
return new AbortablePromise(async function* (await_or_abort) {
|
|
|
|
return new AbortablePromise(async function* (await_or_abort) {
|
|
|
|
return await_or_abort(
|
|
|
|
return await_or_abort(
|
|
|
|
new Promise((resolve, reject) => {
|
|
|
|
new Promise((resolve, _) => {
|
|
|
|
let resolved = false;
|
|
|
|
let resolved = false;
|
|
|
|
const callback = async (arg: L) => {
|
|
|
|
const callback = async (arg: L) => {
|
|
|
|
if (resolved) return;
|
|
|
|
if (resolved) return;
|
|
|
@ -156,55 +168,3 @@ export default class AbortablePromise<T> implements Promise<T | null> {
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
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<void> {
|
|
|
|
|
|
|
|
// 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);
|
|
|
|
|
|
|
|