Cancellable Task Runner With Cleanup
A cancellable task runner that stops starting new work on abort and always runs registered cleanup, even when a task throws mid-flight.
Code
export class AbortError extends Error {
constructor(message = "run aborted") {
super(message);
this.name = "AbortError";
}
}
export async function runTasks(tasks, options = {}) {
const { signal, onCleanup } = options;
const results = [];
const throwIfAborted = () => {
if (signal?.aborted) throw new AbortError();
};
throwIfAborted();
for (const task of tasks) {
let cleanupRan = false;
const cleanup = async () => {
if (cleanupRan) return;
cleanupRan = true;
if (onCleanup) await onCleanup();
};
try {
const value = await task({ signal });
results.push({ ok: true, value });
await cleanup();
} catch (err) {
await cleanup();
throw err;
}
throwIfAborted();
}
return results;
}Report a problem with this exampleOpens a pre-filled issue on GitHub.