@wopjs/async-seq
Version:
Run async functions one-by-one in a sequence.
128 lines (113 loc) • 3.09 kB
text/typescript
import { isAbortable, tryCall } from "./utils";
/**
* Execute task. Optionally returns a disposer function that cleans up side effects.
*/
export interface AsyncSeqFn {
(): (() => Promise<unknown> | unknown) | Promise<() => Promise<unknown> | unknown> | Promise<void> | void;
}
export interface AsyncSeqOptions {
/**
* New pending tasks are added to the sequence tail. By default they are dropped if the sequence is full.
* Set this to `true` to drop old pending tasks from sequence head instead.
*/
dropHead?: boolean;
/**
* Max size of the sequence. Default Infinity.
*/
window?: number;
}
/**
* Run async functions in sequence.
*/
export class AsyncSeq {
/**
* Is sequence full.
*/
public get full(): boolean {
return this.size >= this.
}
/**
* Is sequence running.
*/
public get running(): boolean {
return !!this.
}
/**
* Size of pending tasks in the sequence.
*/
public get size(): number {
return this.
}
readonly
readonly
readonly
public constructor(options?: AsyncSeqOptions) {
this.
this.
this.
}
/**
* Dispose the sequence.
*/
public async dispose(): Promise<void> {
await this.flush();
}
public async flush(): Promise<void> {
this.
await this.
if (this.
await tryCall(this.
this.
}
}
/**
* Add task executors to the sequence.
* @param fns Task executors. Optionally returns a disposer function that cleans up side effects.
* @returns Promise that resolves when all tasks in the sequence are executed.
*/
public async schedule(...fns: AsyncSeqFn[]): Promise<void> {
this.
const diff = this.
if (diff > 0) {
this.
}
await (this.
}
/**
* Wait for the sequence to finish.
*/
public async wait(): Promise<void> {
await this.
}
async
let fn: AsyncSeqFn | undefined;
while ((fn = this.
if (this.
await tryCall(this.
this.
}
const disposer = await tryCall(fn);
if (fn === this.
this.
if (isAbortable(disposer)) {
disposer.abortable(() => {
if (this.
this.
}
});
}
this.
} else {
// stale task
disposer?.();
}
}
this.
}
}
/**
* Run async functions in sequence.
*/
export const seq = (options?: AsyncSeqOptions) => new AsyncSeq(options);