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