some.js (3959B)
1 "use strict"; 2 module.exports = 3 function(Promise, PromiseArray, apiRejection) { 4 var util = require("./util"); 5 var RangeError = require("./errors").RangeError; 6 var AggregateError = require("./errors").AggregateError; 7 var isArray = util.isArray; 8 var CANCELLATION = {}; 9 10 11 function SomePromiseArray(values) { 12 this.constructor$(values); 13 this._howMany = 0; 14 this._unwrap = false; 15 this._initialized = false; 16 } 17 util.inherits(SomePromiseArray, PromiseArray); 18 19 SomePromiseArray.prototype._init = function () { 20 if (!this._initialized) { 21 return; 22 } 23 if (this._howMany === 0) { 24 this._resolve([]); 25 return; 26 } 27 this._init$(undefined, -5); 28 var isArrayResolved = isArray(this._values); 29 if (!this._isResolved() && 30 isArrayResolved && 31 this._howMany > this._canPossiblyFulfill()) { 32 this._reject(this._getRangeError(this.length())); 33 } 34 }; 35 36 SomePromiseArray.prototype.init = function () { 37 this._initialized = true; 38 this._init(); 39 }; 40 41 SomePromiseArray.prototype.setUnwrap = function () { 42 this._unwrap = true; 43 }; 44 45 SomePromiseArray.prototype.howMany = function () { 46 return this._howMany; 47 }; 48 49 SomePromiseArray.prototype.setHowMany = function (count) { 50 this._howMany = count; 51 }; 52 53 SomePromiseArray.prototype._promiseFulfilled = function (value) { 54 this._addFulfilled(value); 55 if (this._fulfilled() === this.howMany()) { 56 this._values.length = this.howMany(); 57 if (this.howMany() === 1 && this._unwrap) { 58 this._resolve(this._values[0]); 59 } else { 60 this._resolve(this._values); 61 } 62 return true; 63 } 64 return false; 65 66 }; 67 SomePromiseArray.prototype._promiseRejected = function (reason) { 68 this._addRejected(reason); 69 return this._checkOutcome(); 70 }; 71 72 SomePromiseArray.prototype._promiseCancelled = function () { 73 if (this._values instanceof Promise || this._values == null) { 74 return this._cancel(); 75 } 76 this._addRejected(CANCELLATION); 77 return this._checkOutcome(); 78 }; 79 80 SomePromiseArray.prototype._checkOutcome = function() { 81 if (this.howMany() > this._canPossiblyFulfill()) { 82 var e = new AggregateError(); 83 for (var i = this.length(); i < this._values.length; ++i) { 84 if (this._values[i] !== CANCELLATION) { 85 e.push(this._values[i]); 86 } 87 } 88 if (e.length > 0) { 89 this._reject(e); 90 } else { 91 this._cancel(); 92 } 93 return true; 94 } 95 return false; 96 }; 97 98 SomePromiseArray.prototype._fulfilled = function () { 99 return this._totalResolved; 100 }; 101 102 SomePromiseArray.prototype._rejected = function () { 103 return this._values.length - this.length(); 104 }; 105 106 SomePromiseArray.prototype._addRejected = function (reason) { 107 this._values.push(reason); 108 }; 109 110 SomePromiseArray.prototype._addFulfilled = function (value) { 111 this._values[this._totalResolved++] = value; 112 }; 113 114 SomePromiseArray.prototype._canPossiblyFulfill = function () { 115 return this.length() - this._rejected(); 116 }; 117 118 SomePromiseArray.prototype._getRangeError = function (count) { 119 var message = "Input array must contain at least " + 120 this._howMany + " items but contains only " + count + " items"; 121 return new RangeError(message); 122 }; 123 124 SomePromiseArray.prototype._resolveEmptyArray = function () { 125 this._reject(this._getRangeError(0)); 126 }; 127 128 function some(promises, howMany) { 129 if ((howMany | 0) !== howMany || howMany < 0) { 130 return apiRejection("expecting a positive integer\u000a\u000a See http://goo.gl/MqrFmX\u000a"); 131 } 132 var ret = new SomePromiseArray(promises); 133 var promise = ret.promise(); 134 ret.setHowMany(howMany); 135 ret.init(); 136 return promise; 137 } 138 139 Promise.some = function (promises, howMany) { 140 return some(promises, howMany); 141 }; 142 143 Promise.prototype.some = function (howMany) { 144 return some(this, howMany); 145 }; 146 147 Promise._SomePromiseArray = SomePromiseArray; 148 };