UNPKG

@techmely/utils

Version:

Collection of helpful JavaScript / TypeScript utils

142 lines (138 loc) 4.08 kB
/*! * @techmely/utils * Copyright(c) 2021-2024 Techmely <techmely.creation@gmail.com> * MIT Licensed */ "use strict"; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // src/p.cancelable.ts var p_cancelable_exports = {}; __export(p_cancelable_exports, { PCancelable: () => PCancelable }); module.exports = __toCommonJS(p_cancelable_exports); var CancelError = class extends Error { constructor(reason) { super(reason || "Promise was canceled"); this.name = "CancelError"; } get isCanceled() { return true; } }; var promiseState = Object.freeze({ pending: Symbol("pending"), canceled: Symbol("canceled"), resolved: Symbol("resolved"), rejected: Symbol("rejected") }); var PCancelable = class _PCancelable extends Promise { static fn(userFunction) { return (...arguments_) => new _PCancelable((resolve, reject, onCancel) => { arguments_.push(onCancel); userFunction(...arguments_).then(resolve, reject); }); } #cancelHandlers = []; #rejectOnCancel = true; #state = promiseState.pending; #promise; #reject = () => { }; constructor(executor) { super(executor); this.#promise = new Promise((resolve, reject) => { this.#reject = reject; const onCancel = (handler) => { if (this.#state !== promiseState.pending) { throw new Error( `The \`onCancel\` handler was attached after the promise ${this.#state.description}.` ); } this.#cancelHandlers.push(handler); }; const addedProperties = { shouldReject: { get: () => this.#rejectOnCancel, set: (boolean) => { this.#rejectOnCancel = boolean; } } }; objectDefProperties(onCancel, addedProperties); const onResolve = (value) => { if (this.#state !== promiseState.canceled || !onCancel.shouldReject) { resolve(value); this.#setState(promiseState.resolved); } }; const onReject = (error) => { if (this.#state !== promiseState.canceled || !onCancel.shouldReject) { reject(error); this.#setState(promiseState.rejected); } }; executor(onResolve, onReject, onCancel); }); } // @ts-expect-error Ignore then then(onFulfilled, onRejected) { return this.#promise.then(onFulfilled, onRejected); } catch(onRejected) { return this.#promise.catch(onRejected); } finally(onFinally) { return this.#promise.finally(onFinally); } cancel(reason) { if (this.#state !== promiseState.pending) { return; } this.#setState(promiseState.canceled); if (this.#cancelHandlers.length > 0) { try { for (const handler of this.#cancelHandlers) { handler(); } } catch (error) { this.#reject(error); return; } } if (this.#rejectOnCancel) { this.#reject(new CancelError(reason)); } } get isCanceled() { return this.#state === promiseState.canceled; } #setState(state) { if (this.#state === promiseState.pending) { this.#state = state; } } }; function objectDefProperties(obj, objAddendum) { Object.defineProperties(obj, objAddendum); } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { PCancelable });