• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wopjs / async-seq / 15457986345

05 Jun 2025 03:49AM UTC coverage: 93.396%. Remained the same
15457986345

push

github

web-flow
chore(deps-dev): bump the dev-dependencies group with 11 updates (#19)

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

27 of 28 branches covered (96.43%)

Branch coverage included in aggregate %.

72 of 78 relevant lines covered (92.31%)

14.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

92.47
/src/async-seq.ts
1
import { isAbortable, tryCall } from "./utils";
1✔
2

3
/**
4
 * Execute task. Optionally returns a disposer function that cleans up side effects.
5
 */
6
export interface AsyncSeqFn {
7
  (): (() => Promise<unknown> | unknown) | Promise<() => Promise<unknown> | unknown> | Promise<void> | void;
8
}
9

10
export interface AsyncSeqOptions {
11
  /**
12
   * New pending tasks are added to the sequence tail. By default they are dropped if the sequence is full.
13
   * Set this to `true` to drop old pending tasks from sequence head instead.
14
   */
15
  dropHead?: boolean;
16
  /**
17
   * Max size of the sequence. Default Infinity.
18
   */
19
  window?: number;
20
}
21

22
/**
23
 * Run async functions in sequence.
24
 */
25
export class AsyncSeq {
1✔
26
  /**
27
   * Is sequence full.
28
   */
29
  public get full(): boolean {
9✔
30
    return this.size >= this.#window;
8✔
31
  }
8✔
32
  /**
33
   * Is sequence running.
34
   */
35
  public get running(): boolean {
9✔
36
    return !!this.#pRunning;
10✔
37
  }
10✔
38

39
  /**
40
   * Size of pending tasks in the sequence.
41
   */
42
  public get size(): number {
9✔
43
    return this.#fns.length;
16✔
44
  }
16✔
45
  #disposer?: (() => any | Promise<any>) | null | void;
9✔
46
  readonly #dropHead: boolean;
9✔
47

48
  readonly #fns: AsyncSeqFn[];
9✔
49

50
  #pRunning?: null | Promise<void>;
9✔
51

52
  readonly #window: number;
9✔
53

54
  public constructor(options?: AsyncSeqOptions) {
9✔
55
    this.#fns = [];
9✔
56
    this.#window = options?.window ?? Infinity;
9✔
57
    this.#dropHead = options?.dropHead ?? false;
9✔
58
  }
9✔
59

60
  /**
61
   * Dispose the sequence.
62
   */
63
  public async dispose(): Promise<void> {
9✔
64
    await this.flush();
8✔
65
  }
8✔
66

67
  public async flush(): Promise<void> {
9✔
68
    this.#fns.length = 0;
8✔
69
    await this.#pRunning;
8✔
70
    if (this.#disposer) {
8✔
71
      await tryCall(this.#disposer);
6✔
72
      this.#disposer = null;
6✔
73
    }
6✔
74
  }
8✔
75

76
  /**
77
   * Add task executors to the sequence.
78
   * @param fns Task executors. Optionally returns a disposer function that cleans up side effects.
79
   * @returns Promise that resolves when all tasks in the sequence are executed.
80
   */
81
  public async schedule(...fns: AsyncSeqFn[]): Promise<void> {
9✔
82
    this.#fns.push(...fns);
20✔
83
    const diff = this.#fns.length - this.#window;
20✔
84
    if (diff > 0) {
20✔
85
      this.#fns.splice(this.#dropHead ? 0 : this.#window, diff);
4✔
86
    }
4✔
87
    await (this.#pRunning ||= this.#run());
20✔
88
  }
20✔
89

90
  /**
91
   * Wait for the sequence to finish.
92
   */
93
  public async wait(): Promise<void> {
9✔
94
    await this.#pRunning;
1✔
95
  }
1✔
96

97
  async #run(): Promise<void> {
9✔
98
    let fn: AsyncSeqFn | undefined;
18✔
99
    while ((fn = this.#fns[0])) {
18✔
100
      if (this.#disposer) {
38✔
101
        await tryCall(this.#disposer);
28✔
102
        this.#disposer = null;
28✔
103
      }
28✔
104
      const disposer = await tryCall(fn);
38✔
105
      if (fn === this.#fns[0]) {
38✔
106
        this.#disposer = disposer;
36✔
107
        if (isAbortable(disposer)) {
36!
108
          disposer.abortable(() => {
×
109
            if (this.#disposer === disposer) {
×
110
              this.#disposer = null;
×
111
            }
×
112
          });
×
113
        }
×
114
        this.#fns.shift();
36✔
115
      } else {
38✔
116
        // stale task
117
        disposer?.();
2✔
118
      }
2✔
119
    }
38✔
120
    this.#pRunning = null;
18✔
121
  }
18✔
122
}
9✔
123

124
/**
125
 * Run async functions in sequence.
126
 */
127
export const seq = (options?: AsyncSeqOptions) => new AsyncSeq(options);
1✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc