You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					117 lines
				
				2.7 KiB
			
		
		
			
		
	
	
					117 lines
				
				2.7 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								'use strict';
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								module.exports = function (PromiseArgument) {
							 | 
						||
| 
								 | 
							
								  var Promise;
							 | 
						||
| 
								 | 
							
								  function throat(size, fn) {
							 | 
						||
| 
								 | 
							
								    var queue = new Queue();
							 | 
						||
| 
								 | 
							
								    function run(fn, self, args) {
							 | 
						||
| 
								 | 
							
								      if (size) {
							 | 
						||
| 
								 | 
							
								        size--;
							 | 
						||
| 
								 | 
							
								        var result = new Promise(function (resolve) {
							 | 
						||
| 
								 | 
							
								          resolve(fn.apply(self, args));
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								        result.then(release, release);
							 | 
						||
| 
								 | 
							
								        return result;
							 | 
						||
| 
								 | 
							
								      } else {
							 | 
						||
| 
								 | 
							
								        return new Promise(function (resolve) {
							 | 
						||
| 
								 | 
							
								          queue.push(new Delayed(resolve, fn, self, args));
							 | 
						||
| 
								 | 
							
								        });
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    function release() {
							 | 
						||
| 
								 | 
							
								      size++;
							 | 
						||
| 
								 | 
							
								      if (!queue.isEmpty()) {
							 | 
						||
| 
								 | 
							
								        var next = queue.shift();
							 | 
						||
| 
								 | 
							
								        next.resolve(run(next.fn, next.self, next.args));
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (typeof size === 'function') {
							 | 
						||
| 
								 | 
							
								      var temp = fn;
							 | 
						||
| 
								 | 
							
								      fn = size;
							 | 
						||
| 
								 | 
							
								      size = temp;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (typeof size !== 'number') {
							 | 
						||
| 
								 | 
							
								      throw new TypeError(
							 | 
						||
| 
								 | 
							
								        'Expected throat size to be a number but got ' + typeof size
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (fn !== undefined && typeof fn !== 'function') {
							 | 
						||
| 
								 | 
							
								      throw new TypeError(
							 | 
						||
| 
								 | 
							
								        'Expected throat fn to be a function but got ' + typeof fn
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    if (typeof fn === 'function') {
							 | 
						||
| 
								 | 
							
								      return function () {
							 | 
						||
| 
								 | 
							
								        var args = [];
							 | 
						||
| 
								 | 
							
								        for (var i = 0; i < arguments.length; i++) {
							 | 
						||
| 
								 | 
							
								          args.push(arguments[i]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return run(fn, this, args);
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      return function (fn) {
							 | 
						||
| 
								 | 
							
								        if (typeof fn !== 'function') {
							 | 
						||
| 
								 | 
							
								          throw new TypeError(
							 | 
						||
| 
								 | 
							
								            'Expected throat fn to be a function but got ' + typeof fn
							 | 
						||
| 
								 | 
							
								          );
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        var args = [];
							 | 
						||
| 
								 | 
							
								        for (var i = 1; i < arguments.length; i++) {
							 | 
						||
| 
								 | 
							
								          args.push(arguments[i]);
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        return run(fn, this, args);
							 | 
						||
| 
								 | 
							
								      };
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  if (arguments.length === 1 && typeof PromiseArgument === 'function') {
							 | 
						||
| 
								 | 
							
								    Promise = PromiseArgument;
							 | 
						||
| 
								 | 
							
								    return throat;
							 | 
						||
| 
								 | 
							
								  } else {
							 | 
						||
| 
								 | 
							
								    Promise = module.exports.Promise;
							 | 
						||
| 
								 | 
							
								    if (typeof Promise !== 'function') {
							 | 
						||
| 
								 | 
							
								      throw new Error(
							 | 
						||
| 
								 | 
							
								        'You must provide a Promise polyfill for this library to work in older environments'
							 | 
						||
| 
								 | 
							
								      );
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    return throat(arguments[0], arguments[1]);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								/* istanbul ignore next */
							 | 
						||
| 
								 | 
							
								if (typeof Promise === 'function') {
							 | 
						||
| 
								 | 
							
								  module.exports.Promise = Promise;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Delayed(resolve, fn, self, args) {
							 | 
						||
| 
								 | 
							
								  this.resolve = resolve;
							 | 
						||
| 
								 | 
							
								  this.fn = fn;
							 | 
						||
| 
								 | 
							
								  this.self = self || null;
							 | 
						||
| 
								 | 
							
								  this.args = args;
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								function Queue() {
							 | 
						||
| 
								 | 
							
								  this._s1 = [];
							 | 
						||
| 
								 | 
							
								  this._s2 = [];
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Queue.prototype.push = function (value) {
							 | 
						||
| 
								 | 
							
								  this._s1.push(value);
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Queue.prototype.shift = function () {
							 | 
						||
| 
								 | 
							
								  var s2 = this._s2;
							 | 
						||
| 
								 | 
							
								  if (s2.length === 0) {
							 | 
						||
| 
								 | 
							
								    var s1 = this._s1;
							 | 
						||
| 
								 | 
							
								    if (s1.length === 0) {
							 | 
						||
| 
								 | 
							
								      return;
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    this._s1 = s2;
							 | 
						||
| 
								 | 
							
								    s2 = this._s2 = s1.reverse();
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return s2.pop();
							 | 
						||
| 
								 | 
							
								};
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								Queue.prototype.isEmpty = function () {
							 | 
						||
| 
								 | 
							
								  return !this._s1.length && !this._s2.length;
							 | 
						||
| 
								 | 
							
								};
							 |