UNPKG

@harlem/task

Version:
69 lines (67 loc) 1.9 kB
// src/errors.ts var TaskAbortError = class extends Error { constructor(reason) { super("Task aborted"); this.reason = reason; } }; // src/index.ts var Task = class extends Promise { constructor(executor, controller = new AbortController()) { if (controller.signal.aborted) { throw new Error("Cannot attach task to an already aborted controller"); } const listeners = /* @__PURE__ */ new Set(); let isAborting = false; let finaliser; super((_resolve, _reject) => { const resolve = (value) => execResolution(() => _resolve(value)); const reject = (reason) => execResolution(() => _reject(reason)); const onAbort = (callback) => listeners.add(callback); const dispose = () => controller.signal.removeEventListener("abort", abort); const execResolution = (resolution) => { if (isAborting) { finaliser = finaliser || resolution; } else { dispose(); resolution(); } }; const abort = () => { isAborting = true; listeners.forEach((listener) => { try { listener(this.abortReason); } finally { listeners.delete(listener); } }); isAborting = false; const finalise = finaliser || ((reason) => _reject(new TaskAbortError(reason))); dispose(); finalise(this.abortReason); }; controller.signal.addEventListener("abort", abort); executor(resolve, reject, controller, onAbort); }); this.controller = controller; } static isTask(value) { return value instanceof Task; } get signal() { return this.controller.signal; } get hasAborted() { return this.signal.aborted; } abort(reason) { this.abortReason = reason; this.controller.abort(); return this; } }; export { TaskAbortError, Task as default };