UNPKG

sussy-util

Version:
300 lines (299 loc) 12.6 kB
"use strict"; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _PromiseUtil_resFirst, _PromiseUtil_resReplace, _PromiseUtil_resLast, _PromiseUtil_MAPPINGS; Object.defineProperty(exports, "__esModule", { value: true }); const IsSomething_1 = __importDefault(require("./IsSomething")); class PromiseUtil { constructor() { /** * Resolves or rejects a promise based on the provided result and error. * * @template R - Type of the promise result. * @template E - Type of the error. * @param {Function} resolve - The resolve function of a promise. * @param {Function} reject - The reject function of a promise. * @param {R} result - The result value of the promise. * @param {E | null} error - The error value of the promise (or null if there is no error). * @private */ _PromiseUtil_resFirst.set(this, (resolve, reject, result, error) => { if (error) { return reject(error); } resolve(result); }); /** * Resolves or rejects a promise based on the provided result, which can be a result value or an error. * * @template R - Type of the promise result. * @template E - Type of the error. * @param {Function} resolve - The resolve function of a promise. * @param {Function} reject - The reject function of a promise. * @param {R | E} result - The result value of the promise (or an error). * @private */ _PromiseUtil_resReplace.set(this, (resolve, reject, result) => { if (result instanceof Error) { return reject(result); } resolve(result); }); /** * Resolves or rejects a promise based on the provided error and result. * * @template R - Type of the promise result. * @template E - Type of the error. * @param {Function} resolve - The resolve function of a promise. * @param {Function} reject - The reject function of a promise. * @param {E | null} error - The error value of the promise (or null if there is no error). * @param {R} result - The result value of the promise. * @private */ _PromiseUtil_resLast.set(this, (resolve, reject, error, result) => { if (error) { return reject(error); } resolve(result); }); /** * Mapping of callback positions and error handling functions. * @private */ _PromiseUtil_MAPPINGS.set(this, { 'front-first': { args: (args, callback) => [callback, ...args], function1: __classPrivateFieldGet(this, _PromiseUtil_resLast, "f"), }, 'front-replace': { args: (args, callback) => [callback, ...args], function1: __classPrivateFieldGet(this, _PromiseUtil_resReplace, "f"), }, 'front-last': { args: (args, callback) => [callback, ...args], function1: __classPrivateFieldGet(this, _PromiseUtil_resFirst, "f"), }, 'back-first': { args: (args, callback) => [...args, callback], function1: __classPrivateFieldGet(this, _PromiseUtil_resLast, "f"), }, 'back-replace': { args: (args, callback) => [...args, callback], function1: __classPrivateFieldGet(this, _PromiseUtil_resReplace, "f"), }, 'back-last': { args: (args, callback) => [...args, callback], function1: __classPrivateFieldGet(this, _PromiseUtil_resFirst, "f"), }, }); } /** * Execute an array of promises sequentially and collect results and errors. * * @template T - Type of the promise results. * @param {PromiseOr<T>[]} promises - Array of promises to execute. * @returns {Promise<[Array<T | null>, Error[]]>} - A promise that resolves to an array of results and errors. */ async executeSequentially(promises) { const errors = []; const results = await promises.reduce(async (chain, promise) => { const results = await chain; const [result, error] = await this.handler(promise); results.push(result); if (error) { errors.push(error); } return results; }, Promise.resolve([])); return [results, errors]; } /** * Handle a promise, including error handling. * * @template R - Type of the promise result. * @template E - Type of the error. * @param {PromiseOr<R> | AsyncFunction<R>} promise - The promise to handle. * @returns {Promise<[R | null, E | null]>} - A promise that resolves to a tuple of result and error. */ async handler(promise) { try { if (IsSomething_1.default.isFunction(promise)) promise = promise(); const data = await promise; return [data, null]; } catch (e) { return [null, e]; } } /** * Retry executing a function with a specified number of retries. * * @template T - Type of the function result. * @param {() => PromiseOr<T>} func - The function to retry. * @param {number} [maxRetries=3] - The maximum number of retries. * @returns {Promise} A promise that resolves to the result and an array of errors. */ async retry(func, maxRetries = 3) { const errors = []; let result = null; for (let i = 0; i <= maxRetries; i++) { try { result = await func(); break; } catch (error) { errors.push(error); } } return [result, errors]; } /** * Delay execution for a specified number of milliseconds. * * @param {number} milliseconds - The delay duration in milliseconds. * @returns {Promise<void>} A promise that resolves after the delay. */ async delay(milliseconds) { return new Promise((resolve) => setTimeout(resolve, milliseconds)); } /** * Filter an array of values using an asynchronous filter function. * * @template T - Type of the values. * @param {T[]} values - The array of values to filter. * @param {(value: T) => PromiseOr<boolean>} asyncFilterFunc - The asynchronous filter function. * @returns {Promise<T[]>} A promise that resolves to the filtered array. */ async filter(values, asyncFilterFunc) { const results = await Promise.all(values.map(async (value) => ({ value, shouldKeep: await asyncFilterFunc(value), }))); return results.filter((result) => result.shouldKeep).map((result) => result.value); } /** * Timeout a promise after a specified duration. * * @template T - Type of the promise result. * @param {PromiseOr<T>} promise - The promise to add a timeout to. * @param {number} milliseconds - The timeout duration in milliseconds. * @returns {Promise<T>} A promise that resolves with the result or rejects with a timeout error. */ async timeout(promise, milliseconds) { return Promise.race([ promise, new Promise((_, reject) => setTimeout(() => reject(new Error('Timeout exceeded')), milliseconds)), ]); } /** * Execute promises in batches and collect results. * * @template T - Type of input values. * @template R - Type of promise results. * @param {T[]} values - Array of input values. * @param {number} batchSize - Size of each batch. * @param {(value: T) => PromiseOr<R>} asyncFunc - Asynchronous function to apply to each value. * @returns {Promise<R[]>} - A promise that resolves to an array of results. */ async batchPromises(values, batchSize, asyncFunc) { const results = []; for (let i = 0; i < values.length; i += batchSize) { const batch = values.slice(i, i + batchSize); const batchResults = await Promise.all(batch.map(asyncFunc)); results.push(...batchResults); } return results; } /** * Promisify a function, allowing customization of callback and error positions. * * @template T - Type of arguments to the function. * @template R - Type of the promise result. * @param {Function} func - The function to promisify. * @param {options} [options={ callBackPosition: "back", errorPosition: "last" }] - Options for customization. * @returns {Function} A promisified function. */ promisify(func, { callBackPosition = 'back', errorPosition = 'last' } = { callBackPosition: 'back', errorPosition: 'last', }) { return (...args) => new Promise((resolve, reject) => { const key = `${callBackPosition}-${errorPosition}`; const current = __classPrivateFieldGet(this, _PromiseUtil_MAPPINGS, "f")[key]; if (!current) throw new Error('ERR: Invalid callBackPosition or errorPosition'); // @ts-expect-error - Dynamic function call func(...current.args(args, current.function1.bind(this, resolve, reject))); }); } /** * Map an array of values to an array of promises and await their results. * @param values Array of values to map to promises. * @param asyncMapFunc Function to map values to promises. * @returns Array of results. */ async mapPromises(values, asyncMapFunc) { return await Promise.all(values.map(asyncMapFunc)); } /** * Concurrently map an array of values to promises with a specified concurrency limit. * @param values Array of values to map to promises. * @param asyncMapFunc Function to map values to promises. * @param concurrency Maximum number of promises to run concurrently. * @returns Array of results. */ async concurrentMap(values, asyncMapFunc, concurrency) { const results = []; let index = 0; async function processNext() { while (index < values.length) { const value = values[index++]; const result = await asyncMapFunc(value); results.push(result); } } const concurrencyPromises = []; for (let i = 0; i < concurrency; i++) { concurrencyPromises.push(processNext()); } await Promise.all(concurrencyPromises); return results; } /** * Execute an array of promises concurrently with a specified concurrency limit. * * @template T - Type of the promise results. * @param {PromiseOr<T>[]} promises - Array of promises to execute. * @param {number} concurrency - Maximum number of promises to run concurrently. * @returns {Promise<[Array<T | null>, Error[]]>} - A promise that resolves to an array of results and errors. */ async executeConcurrently(promises, concurrency) { const errors = []; const results = await this.concurrentMap(promises, async (promise) => { const [result, error] = await this.handler(promise); if (error) { errors.push(error); } return result; }, concurrency); return [results, errors]; } static getInstance() { return this.instance; } } _PromiseUtil_resFirst = new WeakMap(), _PromiseUtil_resReplace = new WeakMap(), _PromiseUtil_resLast = new WeakMap(), _PromiseUtil_MAPPINGS = new WeakMap(); /** * Singleton instance of the PromiseUtil class. * @private * @static */ PromiseUtil.instance = new PromiseUtil(); exports.default = PromiseUtil.getInstance();