diff options
Diffstat (limited to 'node_modules/bluebird/js/main/reduce.js')
-rw-r--r-- | node_modules/bluebird/js/main/reduce.js | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/node_modules/bluebird/js/main/reduce.js b/node_modules/bluebird/js/main/reduce.js new file mode 100644 index 000000000..319222012 --- /dev/null +++ b/node_modules/bluebird/js/main/reduce.js @@ -0,0 +1,146 @@ +"use strict"; +module.exports = function(Promise, + PromiseArray, + apiRejection, + tryConvertToPromise, + INTERNAL) { +var async = require("./async.js"); +var util = require("./util.js"); +var tryCatch = util.tryCatch; +var errorObj = util.errorObj; +function ReductionPromiseArray(promises, fn, accum, _each) { + this.constructor$(promises); + this._promise._captureStackTrace(); + this._preservedValues = _each === INTERNAL ? [] : null; + this._zerothIsAccum = (accum === undefined); + this._gotAccum = false; + this._reducingIndex = (this._zerothIsAccum ? 1 : 0); + this._valuesPhase = undefined; + var maybePromise = tryConvertToPromise(accum, this._promise); + var rejected = false; + var isPromise = maybePromise instanceof Promise; + if (isPromise) { + maybePromise = maybePromise._target(); + if (maybePromise._isPending()) { + maybePromise._proxyPromiseArray(this, -1); + } else if (maybePromise._isFulfilled()) { + accum = maybePromise._value(); + this._gotAccum = true; + } else { + this._reject(maybePromise._reason()); + rejected = true; + } + } + if (!(isPromise || this._zerothIsAccum)) this._gotAccum = true; + this._callback = fn; + this._accum = accum; + if (!rejected) async.invoke(init, this, undefined); +} +function init() { + this._init$(undefined, -5); +} +util.inherits(ReductionPromiseArray, PromiseArray); + +ReductionPromiseArray.prototype._init = function () {}; + +ReductionPromiseArray.prototype._resolveEmptyArray = function () { + if (this._gotAccum || this._zerothIsAccum) { + this._resolve(this._preservedValues !== null + ? [] : this._accum); + } +}; + +ReductionPromiseArray.prototype._promiseFulfilled = function (value, index) { + var values = this._values; + values[index] = value; + var length = this.length(); + var preservedValues = this._preservedValues; + var isEach = preservedValues !== null; + var gotAccum = this._gotAccum; + var valuesPhase = this._valuesPhase; + var valuesPhaseIndex; + if (!valuesPhase) { + valuesPhase = this._valuesPhase = new Array(length); + for (valuesPhaseIndex=0; valuesPhaseIndex<length; ++valuesPhaseIndex) { + valuesPhase[valuesPhaseIndex] = 0; + } + } + valuesPhaseIndex = valuesPhase[index]; + + if (index === 0 && this._zerothIsAccum) { + this._accum = value; + this._gotAccum = gotAccum = true; + valuesPhase[index] = ((valuesPhaseIndex === 0) + ? 1 : 2); + } else if (index === -1) { + this._accum = value; + this._gotAccum = gotAccum = true; + } else { + if (valuesPhaseIndex === 0) { + valuesPhase[index] = 1; + } else { + valuesPhase[index] = 2; + this._accum = value; + } + } + if (!gotAccum) return; + + var callback = this._callback; + var receiver = this._promise._boundTo; + var ret; + + for (var i = this._reducingIndex; i < length; ++i) { + valuesPhaseIndex = valuesPhase[i]; + if (valuesPhaseIndex === 2) { + this._reducingIndex = i + 1; + continue; + } + if (valuesPhaseIndex !== 1) return; + value = values[i]; + this._promise._pushContext(); + if (isEach) { + preservedValues.push(value); + ret = tryCatch(callback).call(receiver, value, i, length); + } + else { + ret = tryCatch(callback) + .call(receiver, this._accum, value, i, length); + } + this._promise._popContext(); + + if (ret === errorObj) return this._reject(ret.e); + + var maybePromise = tryConvertToPromise(ret, this._promise); + if (maybePromise instanceof Promise) { + maybePromise = maybePromise._target(); + if (maybePromise._isPending()) { + valuesPhase[i] = 4; + return maybePromise._proxyPromiseArray(this, i); + } else if (maybePromise._isFulfilled()) { + ret = maybePromise._value(); + } else { + return this._reject(maybePromise._reason()); + } + } + + this._reducingIndex = i + 1; + this._accum = ret; + } + + this._resolve(isEach ? preservedValues : this._accum); +}; + +function reduce(promises, fn, initialValue, _each) { + if (typeof fn !== "function") return apiRejection("fn must be a function\u000a\u000a See http://goo.gl/916lJJ\u000a"); + var array = new ReductionPromiseArray(promises, fn, initialValue, _each); + return array.promise(); +} + +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); +}; +}; |