2 module.exports = function(Promise,
8 var getDomain = Promise._getDomain;
9 var util = require("./util");
10 var tryCatch = util.tryCatch;
12 function ReductionPromiseArray(promises, fn, initialValue, _each) {
13 this.constructor$(promises);
14 var domain = getDomain();
15 this._fn = domain === null ? fn : domain.bind(fn);
16 if (initialValue !== undefined) {
17 initialValue = Promise.resolve(initialValue);
18 initialValue._attachCancellationCallback(this);
20 this._initialValue = initialValue;
21 this._currentCancellable = null;
22 this._eachValues = _each === INTERNAL ? [] : undefined;
23 this._promise._captureStackTrace();
24 this._init$(undefined, -5);
26 util.inherits(ReductionPromiseArray, PromiseArray);
28 ReductionPromiseArray.prototype._gotAccum = function(accum) {
29 if (this._eachValues !== undefined && accum !== INTERNAL) {
30 this._eachValues.push(accum);
34 ReductionPromiseArray.prototype._eachComplete = function(value) {
35 this._eachValues.push(value);
36 return this._eachValues;
39 ReductionPromiseArray.prototype._init = function() {};
41 ReductionPromiseArray.prototype._resolveEmptyArray = function() {
42 this._resolve(this._eachValues !== undefined ? this._eachValues
43 : this._initialValue);
46 ReductionPromiseArray.prototype.shouldCopyValues = function () {
50 ReductionPromiseArray.prototype._resolve = function(value) {
51 this._promise._resolveCallback(value);
55 ReductionPromiseArray.prototype._resultCancelled = function(sender) {
56 if (sender === this._initialValue) return this._cancel();
57 if (this._isResolved()) return;
58 this._resultCancelled$();
59 if (this._currentCancellable instanceof Promise) {
60 this._currentCancellable.cancel();
62 if (this._initialValue instanceof Promise) {
63 this._initialValue.cancel();
67 ReductionPromiseArray.prototype._iterate = function (values) {
68 this._values = values;
71 var length = values.length;
72 if (this._initialValue !== undefined) {
73 value = this._initialValue;
76 value = Promise.resolve(values[0]);
80 this._currentCancellable = value;
82 if (!value.isRejected()) {
83 for (; i < length; ++i) {
91 value = value._then(gotAccum, undefined, undefined, ctx, undefined);
95 if (this._eachValues !== undefined) {
97 ._then(this._eachComplete, undefined, undefined, this, undefined);
99 value._then(completed, completed, undefined, value, this);
102 Promise.prototype.reduce = function (fn, initialValue) {
103 return reduce(this, fn, initialValue, null);
106 Promise.reduce = function (promises, fn, initialValue, _each) {
107 return reduce(promises, fn, initialValue, _each);
110 function completed(valueOrReason, array) {
111 if (this.isFulfilled()) {
112 array._resolve(valueOrReason);
114 array._reject(valueOrReason);
118 function reduce(promises, fn, initialValue, _each) {
119 if (typeof fn !== "function") {
120 return apiRejection("expecting a function but got " + util.classString(fn));
122 var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
123 return array.promise();
126 function gotAccum(accum) {
128 this.array._gotAccum(accum);
129 var value = tryConvertToPromise(this.value, this.array._promise);
130 if (value instanceof Promise) {
131 this.array._currentCancellable = value;
132 return value._then(gotValue, undefined, undefined, this, undefined);
134 return gotValue.call(this, value);
138 function gotValue(value) {
139 var array = this.array;
140 var promise = array._promise;
141 var fn = tryCatch(array._fn);
142 promise._pushContext();
144 if (array._eachValues !== undefined) {
145 ret = fn.call(promise._boundValue(), value, this.index, this.length);
147 ret = fn.call(promise._boundValue(),
148 this.accum, value, this.index, this.length);
150 if (ret instanceof Promise) {
151 array._currentCancellable = ret;
153 var promiseCreated = promise._popContext();
154 debug.checkForgottenReturns(
157 array._eachValues !== undefined ? "Promise.each" : "Promise.reduce",