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.
		
		
		
		
		
			
		
			
				
					
					
						
							183 lines
						
					
					
						
							5.2 KiB
						
					
					
				
			
		
		
	
	
							183 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; | 
						|
} | 
						|
};
 | 
						|
 |