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.
		
		
		
		
		
			
		
			
				
					
					
						
							184 lines
						
					
					
						
							5.2 KiB
						
					
					
				
			
		
		
	
	
							184 lines
						
					
					
						
							5.2 KiB
						
					
					
				| "use strict";
 | |
| module.exports = function(Promise,
 | |
|                           PromiseArray,
 | |
|                           apiRejection,
 | |
|                           tryConvertToPromise,
 | |
|                           INTERNAL,
 | |
|                           debug) {
 | |
| var util = require("./util");
 | |
| var tryCatch = util.tryCatch;
 | |
| 
 | |
| function ReductionPromiseArray(promises, fn, initialValue, _each) {
 | |
|     this.constructor$(promises);
 | |
|     var context = Promise._getContext();
 | |
|     this._fn = util.contextBind(context, fn);
 | |
|     if (initialValue !== undefined) {
 | |
|         initialValue = Promise.resolve(initialValue);
 | |
|         initialValue._attachCancellationCallback(this);
 | |
|     }
 | |
|     this._initialValue = initialValue;
 | |
|     this._currentCancellable = null;
 | |
|     if(_each === INTERNAL) {
 | |
|         this._eachValues = Array(this._length);
 | |
|     } else if (_each === 0) {
 | |
|         this._eachValues = null;
 | |
|     } else {
 | |
|         this._eachValues = undefined;
 | |
|     }
 | |
|     this._promise._captureStackTrace();
 | |
|     this._init$(undefined, -5);
 | |
| }
 | |
| util.inherits(ReductionPromiseArray, PromiseArray);
 | |
| 
 | |
| ReductionPromiseArray.prototype._gotAccum = function(accum) {
 | |
|     if (this._eachValues !== undefined &&
 | |
|         this._eachValues !== null &&
 | |
|         accum !== INTERNAL) {
 | |
|         this._eachValues.push(accum);
 | |
|     }
 | |
| };
 | |
| 
 | |
| ReductionPromiseArray.prototype._eachComplete = function(value) {
 | |
|     if (this._eachValues !== null) {
 | |
|         this._eachValues.push(value);
 | |
|     }
 | |
|     return this._eachValues;
 | |
| };
 | |
| 
 | |
| ReductionPromiseArray.prototype._init = function() {};
 | |
| 
 | |
| ReductionPromiseArray.prototype._resolveEmptyArray = function() {
 | |
|     this._resolve(this._eachValues !== undefined ? this._eachValues
 | |
|                                                  : this._initialValue);
 | |
| };
 | |
| 
 | |
| ReductionPromiseArray.prototype.shouldCopyValues = function () {
 | |
|     return false;
 | |
| };
 | |
| 
 | |
| ReductionPromiseArray.prototype._resolve = function(value) {
 | |
|     this._promise._resolveCallback(value);
 | |
|     this._values = null;
 | |
| };
 | |
| 
 | |
| ReductionPromiseArray.prototype._resultCancelled = function(sender) {
 | |
|     if (sender === this._initialValue) return this._cancel();
 | |
|     if (this._isResolved()) return;
 | |
|     this._resultCancelled$();
 | |
|     if (this._currentCancellable instanceof Promise) {
 | |
|         this._currentCancellable.cancel();
 | |
|     }
 | |
|     if (this._initialValue instanceof Promise) {
 | |
|         this._initialValue.cancel();
 | |
|     }
 | |
| };
 | |
| 
 | |
| ReductionPromiseArray.prototype._iterate = function (values) {
 | |
|     this._values = values;
 | |
|     var value;
 | |
|     var i;
 | |
|     var length = values.length;
 | |
|     if (this._initialValue !== undefined) {
 | |
|         value = this._initialValue;
 | |
|         i = 0;
 | |
|     } else {
 | |
|         value = Promise.resolve(values[0]);
 | |
|         i = 1;
 | |
|     }
 | |
| 
 | |
|     this._currentCancellable = value;
 | |
| 
 | |
|     for (var j = i; j < length; ++j) {
 | |
|         var maybePromise = values[j];
 | |
|         if (maybePromise instanceof Promise) {
 | |
|             maybePromise.suppressUnhandledRejections();
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!value.isRejected()) {
 | |
|         for (; i < length; ++i) {
 | |
|             var ctx = {
 | |
|                 accum: null,
 | |
|                 value: values[i],
 | |
|                 index: i,
 | |
|                 length: length,
 | |
|                 array: this
 | |
|             };
 | |
| 
 | |
|             value = value._then(gotAccum, undefined, undefined, ctx, undefined);
 | |
| 
 | |
|             if ((i & 127) === 0) {
 | |
|                 value._setNoAsyncGuarantee();
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (this._eachValues !== undefined) {
 | |
|         value = value
 | |
|             ._then(this._eachComplete, undefined, undefined, this, undefined);
 | |
|     }
 | |
|     value._then(completed, completed, undefined, value, this);
 | |
| };
 | |
| 
 | |
| Promise.prototype.reduce = function (fn, initialValue) {
 | |
|     return reduce(this, fn, initialValue, null);
 | |
| };
 | |
| 
 | |
| Promise.reduce = function (promises, fn, initialValue, _each) {
 | |
|     return reduce(promises, fn, initialValue, _each);
 | |
| };
 | |
| 
 | |
| function completed(valueOrReason, array) {
 | |
|     if (this.isFulfilled()) {
 | |
|         array._resolve(valueOrReason);
 | |
|     } else {
 | |
|         array._reject(valueOrReason);
 | |
|     }
 | |
| }
 | |
| 
 | |
| function reduce(promises, fn, initialValue, _each) {
 | |
|     if (typeof fn !== "function") {
 | |
|         return apiRejection("expecting a function but got " + util.classString(fn));
 | |
|     }
 | |
|     var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
 | |
|     return array.promise();
 | |
| }
 | |
| 
 | |
| function gotAccum(accum) {
 | |
|     this.accum = accum;
 | |
|     this.array._gotAccum(accum);
 | |
|     var value = tryConvertToPromise(this.value, this.array._promise);
 | |
|     if (value instanceof Promise) {
 | |
|         this.array._currentCancellable = value;
 | |
|         return value._then(gotValue, undefined, undefined, this, undefined);
 | |
|     } else {
 | |
|         return gotValue.call(this, value);
 | |
|     }
 | |
| }
 | |
| 
 | |
| function gotValue(value) {
 | |
|     var array = this.array;
 | |
|     var promise = array._promise;
 | |
|     var fn = tryCatch(array._fn);
 | |
|     promise._pushContext();
 | |
|     var ret;
 | |
|     if (array._eachValues !== undefined) {
 | |
|         ret = fn.call(promise._boundValue(), value, this.index, this.length);
 | |
|     } else {
 | |
|         ret = fn.call(promise._boundValue(),
 | |
|                               this.accum, value, this.index, this.length);
 | |
|     }
 | |
|     if (ret instanceof Promise) {
 | |
|         array._currentCancellable = ret;
 | |
|     }
 | |
|     var promiseCreated = promise._popContext();
 | |
|     debug.checkForgottenReturns(
 | |
|         ret,
 | |
|         promiseCreated,
 | |
|         array._eachValues !== undefined ? "Promise.each" : "Promise.reduce",
 | |
|         promise
 | |
|     );
 | |
|     return ret;
 | |
| }
 | |
| };
 |