Skip to content

Commit 0743123

Browse files
重构 compileToSvgDebounced
1 parent 46acc8c commit 0743123

File tree

1 file changed

+36
-53
lines changed

1 file changed

+36
-53
lines changed

src/compiler/index.ts

Lines changed: 36 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -296,62 +296,45 @@ export const compileToSvg = (data: ContestData<{ withMarkdown: true }>) =>
296296
send<RenderTypstMessage>("renderTypst", worker, compilerPrepare(data));
297297

298298
export const compileToSvgDebounced = (() => {
299-
let inFlight: Promise<string | undefined> | undefined = undefined;
300-
let pendingData: ContestData<{ withMarkdown: true }> | undefined = undefined;
301-
let nextDeferred:
302-
| {
303-
resolve: (v: string | undefined) => void;
304-
reject: (e: unknown) => void;
305-
promise: Promise<string | undefined>;
306-
}
307-
| undefined = undefined;
308-
309-
const runNext = () => {
310-
if (!pendingData) {
311-
// Nothing to run next
312-
inFlight = undefined;
313-
return;
314-
}
315-
const data = pendingData;
316-
pendingData = undefined;
317-
const deferred = nextDeferred!;
318-
nextDeferred = undefined;
319-
inFlight = compileToSvg(data)
320-
.then((res) => {
321-
deferred.resolve(res);
322-
return res;
323-
})
324-
.catch((err) => {
325-
deferred.reject(err);
326-
throw err;
327-
})
328-
.finally(() => {
329-
if (pendingData) runNext();
330-
else inFlight = undefined;
331-
});
299+
type Task = {
300+
args: ContestData<{ withMarkdown: true }>;
301+
promise: Promise<string | undefined>;
302+
resolve: (v: string | undefined) => void;
303+
reject: (e: unknown) => void;
332304
};
305+
let currentTask: Task | undefined = undefined;
306+
let waitingTask: Task | undefined = undefined;
333307

334-
return (data: ContestData<{ withMarkdown: true }>) => {
335-
if (!inFlight) {
336-
// No job running, execute immediately
337-
inFlight = compileToSvg(data).finally(() => {
338-
if (pendingData) runNext();
339-
else inFlight = undefined;
340-
});
341-
return inFlight;
342-
}
343-
// A job is running: coalesce into the next run with the latest data
344-
pendingData = data;
345-
if (!nextDeferred) {
346-
let resolve!: (v: string | undefined) => void;
347-
let reject!: (e: unknown) => void;
348-
const promise = new Promise<string | undefined>((res, rej) => {
349-
resolve = res;
350-
reject = rej;
308+
const run = () => {
309+
if (currentTask) return;
310+
if (waitingTask) {
311+
currentTask = waitingTask;
312+
waitingTask = undefined;
313+
} else return;
314+
const task = currentTask;
315+
compileToSvg(task.args)
316+
.then(task.resolve, task.reject)
317+
.then(() => {
318+
currentTask = undefined;
319+
run();
351320
});
352-
nextDeferred = { resolve, reject, promise };
353-
}
354-
return nextDeferred.promise;
321+
};
322+
return (args: ContestData<{ withMarkdown: true }>) => {
323+
let resolve: (v: string | undefined) => void, reject: (e: unknown) => void;
324+
const promise = new Promise<string | undefined>((res, rej) => {
325+
resolve = res;
326+
reject = rej;
327+
});
328+
const newTask: Task = {
329+
args,
330+
promise,
331+
resolve: resolve!,
332+
reject: reject!,
333+
};
334+
if (waitingTask) waitingTask.reject("Aborted");
335+
waitingTask = newTask;
336+
run();
337+
return promise;
355338
};
356339
})();
357340

0 commit comments

Comments
 (0)