返回 DeepSeek-Reasonix
captureQueue.ts
根目录 / desktop / electron / src / main / browser / captureQueue.ts
1 import { browserFailure } from "./errors.js";
2
3 // One temporary native host at a time. Cancellation removes queued work without
4 // ever borrowing the surface owned by the preceding request.
5 export class CaptureQueue {
6 private tail: Promise<void> = Promise.resolve();
7
8 async run<T>(signal: AbortSignal, work: () => Promise<T>): Promise<T> {
9 const previous = this.tail;
10 let release!: () => void;
11 const slot = new Promise<void>((resolve) => { release = resolve; });
12 this.tail = previous.then(() => slot);
13 try {
14 await abortable(previous, signal);
15 signal.throwIfAborted();
16 return await work();
17 } finally { release(); }
18 }
19 }
20
21 export function abortable<T>(promise: Promise<T>, signal: AbortSignal): Promise<T> {
22 return new Promise<T>((resolve, reject) => {
23 const abort = () => reject(signal.reason?.code < 0 ? signal.reason : browserFailure("cancelled", "browser request cancelled or expired"));
24 // The operation may already be running, even when its waiter is cancelled.
25 // Always consume its eventual rejection before taking the early-abort path.
26 promise.then(resolve, reject).finally(() => signal.removeEventListener("abort", abort));
27 if (signal.aborted) { abort(); return; }
28 signal.addEventListener("abort", abort, { once: true });
29 });
30 }
31
31 lines TYPESCRIPT