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.
		
		
		
		
		
			
		
			
				
					176 lines
				
				5.5 KiB
			
		
		
			
		
	
	
					176 lines
				
				5.5 KiB
			| 
											3 years ago
										 | "use strict"; | ||
|  | module.exports = function(Promise, | ||
|  |                           PromiseArray, | ||
|  |                           apiRejection, | ||
|  |                           tryConvertToPromise, | ||
|  |                           INTERNAL, | ||
|  |                           debug) { | ||
|  | var util = require("./util"); | ||
|  | var tryCatch = util.tryCatch; | ||
|  | var errorObj = util.errorObj; | ||
|  | var async = Promise._async; | ||
|  | 
 | ||
|  | function MappingPromiseArray(promises, fn, limit, _filter) { | ||
|  |     this.constructor$(promises); | ||
|  |     this._promise._captureStackTrace(); | ||
|  |     var context = Promise._getContext(); | ||
|  |     this._callback = util.contextBind(context, fn); | ||
|  |     this._preservedValues = _filter === INTERNAL | ||
|  |         ? new Array(this.length()) | ||
|  |         : null; | ||
|  |     this._limit = limit; | ||
|  |     this._inFlight = 0; | ||
|  |     this._queue = []; | ||
|  |     async.invoke(this._asyncInit, this, undefined); | ||
|  |     if (util.isArray(promises)) { | ||
|  |         for (var i = 0; i < promises.length; ++i) { | ||
|  |             var maybePromise = promises[i]; | ||
|  |             if (maybePromise instanceof Promise) { | ||
|  |                 maybePromise.suppressUnhandledRejections(); | ||
|  |             } | ||
|  |         } | ||
|  |     } | ||
|  | } | ||
|  | util.inherits(MappingPromiseArray, PromiseArray); | ||
|  | 
 | ||
|  | MappingPromiseArray.prototype._asyncInit = function() { | ||
|  |     this._init$(undefined, -2); | ||
|  | }; | ||
|  | 
 | ||
|  | MappingPromiseArray.prototype._init = function () {}; | ||
|  | 
 | ||
|  | MappingPromiseArray.prototype._promiseFulfilled = function (value, index) { | ||
|  |     var values = this._values; | ||
|  |     var length = this.length(); | ||
|  |     var preservedValues = this._preservedValues; | ||
|  |     var limit = this._limit; | ||
|  | 
 | ||
|  |     if (index < 0) { | ||
|  |         index = (index * -1) - 1; | ||
|  |         values[index] = value; | ||
|  |         if (limit >= 1) { | ||
|  |             this._inFlight--; | ||
|  |             this._drainQueue(); | ||
|  |             if (this._isResolved()) return true; | ||
|  |         } | ||
|  |     } else { | ||
|  |         if (limit >= 1 && this._inFlight >= limit) { | ||
|  |             values[index] = value; | ||
|  |             this._queue.push(index); | ||
|  |             return false; | ||
|  |         } | ||
|  |         if (preservedValues !== null) preservedValues[index] = value; | ||
|  | 
 | ||
|  |         var promise = this._promise; | ||
|  |         var callback = this._callback; | ||
|  |         var receiver = promise._boundValue(); | ||
|  |         promise._pushContext(); | ||
|  |         var ret = tryCatch(callback).call(receiver, value, index, length); | ||
|  |         var promiseCreated = promise._popContext(); | ||
|  |         debug.checkForgottenReturns( | ||
|  |             ret, | ||
|  |             promiseCreated, | ||
|  |             preservedValues !== null ? "Promise.filter" : "Promise.map", | ||
|  |             promise | ||
|  |         ); | ||
|  |         if (ret === errorObj) { | ||
|  |             this._reject(ret.e); | ||
|  |             return true; | ||
|  |         } | ||
|  | 
 | ||
|  |         var maybePromise = tryConvertToPromise(ret, this._promise); | ||
|  |         if (maybePromise instanceof Promise) { | ||
|  |             maybePromise = maybePromise._target(); | ||
|  |             var bitField = maybePromise._bitField; | ||
|  |             ; | ||
|  |             if (((bitField & 50397184) === 0)) { | ||
|  |                 if (limit >= 1) this._inFlight++; | ||
|  |                 values[index] = maybePromise; | ||
|  |                 maybePromise._proxy(this, (index + 1) * -1); | ||
|  |                 return false; | ||
|  |             } else if (((bitField & 33554432) !== 0)) { | ||
|  |                 ret = maybePromise._value(); | ||
|  |             } else if (((bitField & 16777216) !== 0)) { | ||
|  |                 this._reject(maybePromise._reason()); | ||
|  |                 return true; | ||
|  |             } else { | ||
|  |                 this._cancel(); | ||
|  |                 return true; | ||
|  |             } | ||
|  |         } | ||
|  |         values[index] = ret; | ||
|  |     } | ||
|  |     var totalResolved = ++this._totalResolved; | ||
|  |     if (totalResolved >= length) { | ||
|  |         if (preservedValues !== null) { | ||
|  |             this._filter(values, preservedValues); | ||
|  |         } else { | ||
|  |             this._resolve(values); | ||
|  |         } | ||
|  |         return true; | ||
|  |     } | ||
|  |     return false; | ||
|  | }; | ||
|  | 
 | ||
|  | MappingPromiseArray.prototype._drainQueue = function () { | ||
|  |     var queue = this._queue; | ||
|  |     var limit = this._limit; | ||
|  |     var values = this._values; | ||
|  |     while (queue.length > 0 && this._inFlight < limit) { | ||
|  |         if (this._isResolved()) return; | ||
|  |         var index = queue.pop(); | ||
|  |         this._promiseFulfilled(values[index], index); | ||
|  |     } | ||
|  | }; | ||
|  | 
 | ||
|  | MappingPromiseArray.prototype._filter = function (booleans, values) { | ||
|  |     var len = values.length; | ||
|  |     var ret = new Array(len); | ||
|  |     var j = 0; | ||
|  |     for (var i = 0; i < len; ++i) { | ||
|  |         if (booleans[i]) ret[j++] = values[i]; | ||
|  |     } | ||
|  |     ret.length = j; | ||
|  |     this._resolve(ret); | ||
|  | }; | ||
|  | 
 | ||
|  | MappingPromiseArray.prototype.preservedValues = function () { | ||
|  |     return this._preservedValues; | ||
|  | }; | ||
|  | 
 | ||
|  | function map(promises, fn, options, _filter) { | ||
|  |     if (typeof fn !== "function") { | ||
|  |         return apiRejection("expecting a function but got " + util.classString(fn)); | ||
|  |     } | ||
|  | 
 | ||
|  |     var limit = 0; | ||
|  |     if (options !== undefined) { | ||
|  |         if (typeof options === "object" && options !== null) { | ||
|  |             if (typeof options.concurrency !== "number") { | ||
|  |                 return Promise.reject( | ||
|  |                     new TypeError("'concurrency' must be a number but it is " + | ||
|  |                                     util.classString(options.concurrency))); | ||
|  |             } | ||
|  |             limit = options.concurrency; | ||
|  |         } else { | ||
|  |             return Promise.reject(new TypeError( | ||
|  |                             "options argument must be an object but it is " + | ||
|  |                              util.classString(options))); | ||
|  |         } | ||
|  |     } | ||
|  |     limit = typeof limit === "number" && | ||
|  |         isFinite(limit) && limit >= 1 ? limit : 0; | ||
|  |     return new MappingPromiseArray(promises, fn, limit, _filter).promise(); | ||
|  | } | ||
|  | 
 | ||
|  | Promise.prototype.map = function (fn, options) { | ||
|  |     return map(this, fn, options, null); | ||
|  | }; | ||
|  | 
 | ||
|  | Promise.map = function (promises, fn, options, _filter) { | ||
|  |     return map(promises, fn, options, _filter); | ||
|  | }; | ||
|  | 
 | ||
|  | 
 | ||
|  | }; |