|
|
- "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;
- }
- };
|