"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); var DEFAULT_MAX = 5; /** * Default checker which validates if a next task should begin. * This can be overwritten to write own checks for example checking the amount * of used ram and waiting till the ram is low enough for a next task. * * It should always resolve with a boolean, either `true` to start a next task * or `false` to stop executing a new task. * * If this method rejects, the error will propagate to the caller * @param status * @param tasks * @returns {Promise} */ var defaultNextTaskCheck = function (status, tasks) { return new Promise(function (resolve, reject) { resolve(status.amountStarted < tasks.length); }); }; var DEFAULT_OPTIONS = { maxInProgress: DEFAULT_MAX, failFast: false, nextCheck: defaultNextTaskCheck }; /** * Raw throttle function, which can return extra meta data. * @param tasks required array of tasks to be executed * @param options Options object * @returns {Promise} */ function raw(tasks, options) { return new Promise(function (resolve, reject) { var myOptions = Object.assign({}, DEFAULT_OPTIONS, options); var result = { amountDone: 0, amountStarted: 0, amountResolved: 0, amountRejected: 0, amountNextCheckFalsey: 0, rejectedIndexes: [], resolvedIndexes: [], nextCheckFalseyIndexes: [], taskResults: [] }; if (tasks.length === 0) { return resolve(result); } var failedFast = false; var currentTaskIndex = 0; var executeTask = function (index) { result.amountStarted++; if (typeof tasks[index] === 'function') { tasks[index]().then(function (taskResult) { result.taskResults[index] = taskResult; result.resolvedIndexes.push(index); result.amountResolved++; taskDone(); }, function (error) { result.taskResults[index] = error; result.rejectedIndexes.push(index); result.amountRejected++; if (myOptions.failFast === true) { failedFast = true; return reject(result); } taskDone(); }); } else { failedFast = true; return reject(new Error('tasks[' + index + ']: ' + tasks[index] + ', is supposed to be of type function')); } }; var taskDone = function () { //make sure no more tasks are spawned when we failedFast if (failedFast === true) { return; } result.amountDone++; if (typeof myOptions.progressCallback === 'function') { myOptions.progressCallback(result); } if (result.amountDone === tasks.length) { return resolve(result); } if (currentTaskIndex < tasks.length) { nextTask(currentTaskIndex++); } }; var nextTask = function (index) { //check if we can execute the next task myOptions.nextCheck(result, tasks).then(function (canExecuteNextTask) { if (canExecuteNextTask === true) { //execute it executeTask(index); } else { result.amountNextCheckFalsey++; result.nextCheckFalseyIndexes.push(index); taskDone(); } }, reject); }; //spawn the first X task for (var i = 0; i < Math.min(myOptions.maxInProgress, tasks.length); i++) { nextTask(currentTaskIndex++); } }); } exports.raw = raw; /** * Executes the raw function, but only return the task array * @param tasks * @param options * @returns {Promise} */ function executeRaw(tasks, options) { return new Promise(function (resolve, reject) { raw(tasks, options).then(function (result) { resolve(result.taskResults); }, function (error) { if (error instanceof Error) { reject(error); } else { reject(error.taskResults[error.rejectedIndexes[0]]); } }); }); } /** * Simply run all the promises after each other, so in synchronous manner * @param tasks required array of tasks to be executed * @param options Options object * @returns {Promise} */ function sync(tasks, options) { var myOptions = Object.assign({}, { maxInProgress: 1, failFast: true }, options); return executeRaw(tasks, myOptions); } exports.sync = sync; /** * Exposes the same behaviour as Promise.All(), but throttled! * @param tasks required array of tasks to be executed * @param options Options object * @returns {Promise} */ function all(tasks, options) { var myOptions = Object.assign({}, { failFast: true }, options); return executeRaw(tasks, myOptions); } exports.all = all; //# sourceMappingURL=throttle.js.map