8f73500dd410884582da52b33326bb2ac9dd5cfa
[yaffs-website] / node_modules / bluebird / js / release / reduce.js
1 "use strict";
2 module.exports = function(Promise,
3                           PromiseArray,
4                           apiRejection,
5                           tryConvertToPromise,
6                           INTERNAL,
7                           debug) {
8 var getDomain = Promise._getDomain;
9 var util = require("./util");
10 var tryCatch = util.tryCatch;
11
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);
19     }
20     this._initialValue = initialValue;
21     this._currentCancellable = null;
22     this._eachValues = _each === INTERNAL ? [] : undefined;
23     this._promise._captureStackTrace();
24     this._init$(undefined, -5);
25 }
26 util.inherits(ReductionPromiseArray, PromiseArray);
27
28 ReductionPromiseArray.prototype._gotAccum = function(accum) {
29     if (this._eachValues !== undefined && accum !== INTERNAL) {
30         this._eachValues.push(accum);
31     }
32 };
33
34 ReductionPromiseArray.prototype._eachComplete = function(value) {
35     this._eachValues.push(value);
36     return this._eachValues;
37 };
38
39 ReductionPromiseArray.prototype._init = function() {};
40
41 ReductionPromiseArray.prototype._resolveEmptyArray = function() {
42     this._resolve(this._eachValues !== undefined ? this._eachValues
43                                                  : this._initialValue);
44 };
45
46 ReductionPromiseArray.prototype.shouldCopyValues = function () {
47     return false;
48 };
49
50 ReductionPromiseArray.prototype._resolve = function(value) {
51     this._promise._resolveCallback(value);
52     this._values = null;
53 };
54
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();
61     }
62     if (this._initialValue instanceof Promise) {
63         this._initialValue.cancel();
64     }
65 };
66
67 ReductionPromiseArray.prototype._iterate = function (values) {
68     this._values = values;
69     var value;
70     var i;
71     var length = values.length;
72     if (this._initialValue !== undefined) {
73         value = this._initialValue;
74         i = 0;
75     } else {
76         value = Promise.resolve(values[0]);
77         i = 1;
78     }
79
80     this._currentCancellable = value;
81
82     if (!value.isRejected()) {
83         for (; i < length; ++i) {
84             var ctx = {
85                 accum: null,
86                 value: values[i],
87                 index: i,
88                 length: length,
89                 array: this
90             };
91             value = value._then(gotAccum, undefined, undefined, ctx, undefined);
92         }
93     }
94
95     if (this._eachValues !== undefined) {
96         value = value
97             ._then(this._eachComplete, undefined, undefined, this, undefined);
98     }
99     value._then(completed, completed, undefined, value, this);
100 };
101
102 Promise.prototype.reduce = function (fn, initialValue) {
103     return reduce(this, fn, initialValue, null);
104 };
105
106 Promise.reduce = function (promises, fn, initialValue, _each) {
107     return reduce(promises, fn, initialValue, _each);
108 };
109
110 function completed(valueOrReason, array) {
111     if (this.isFulfilled()) {
112         array._resolve(valueOrReason);
113     } else {
114         array._reject(valueOrReason);
115     }
116 }
117
118 function reduce(promises, fn, initialValue, _each) {
119     if (typeof fn !== "function") {
120         return apiRejection("expecting a function but got " + util.classString(fn));
121     }
122     var array = new ReductionPromiseArray(promises, fn, initialValue, _each);
123     return array.promise();
124 }
125
126 function gotAccum(accum) {
127     this.accum = 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);
133     } else {
134         return gotValue.call(this, value);
135     }
136 }
137
138 function gotValue(value) {
139     var array = this.array;
140     var promise = array._promise;
141     var fn = tryCatch(array._fn);
142     promise._pushContext();
143     var ret;
144     if (array._eachValues !== undefined) {
145         ret = fn.call(promise._boundValue(), value, this.index, this.length);
146     } else {
147         ret = fn.call(promise._boundValue(),
148                               this.accum, value, this.index, this.length);
149     }
150     if (ret instanceof Promise) {
151         array._currentCancellable = ret;
152     }
153     var promiseCreated = promise._popContext();
154     debug.checkForgottenReturns(
155         ret,
156         promiseCreated,
157         array._eachValues !== undefined ? "Promise.each" : "Promise.reduce",
158         promise
159     );
160     return ret;
161 }
162 };