some.js 3.9 KB

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