155 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			155 lines
		
	
	
		
			5.2 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
"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
 |