promise_array.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. "use strict";
  2. module.exports = function(Promise, INTERNAL, tryConvertToPromise,
  3. apiRejection, Proxyable) {
  4. var util = require("./util");
  5. var isArray = util.isArray;
  6. function toResolutionValue(val) {
  7. switch(val) {
  8. case -2: return [];
  9. case -3: return {};
  10. }
  11. }
  12. function PromiseArray(values) {
  13. var promise = this._promise = new Promise(INTERNAL);
  14. if (values instanceof Promise) {
  15. promise._propagateFrom(values, 3);
  16. }
  17. promise._setOnCancel(this);
  18. this._values = values;
  19. this._length = 0;
  20. this._totalResolved = 0;
  21. this._init(undefined, -2);
  22. }
  23. util.inherits(PromiseArray, Proxyable);
  24. PromiseArray.prototype.length = function () {
  25. return this._length;
  26. };
  27. PromiseArray.prototype.promise = function () {
  28. return this._promise;
  29. };
  30. PromiseArray.prototype._init = function init(_, resolveValueIfEmpty) {
  31. var values = tryConvertToPromise(this._values, this._promise);
  32. if (values instanceof Promise) {
  33. values = values._target();
  34. var bitField = values._bitField;
  35. ;
  36. this._values = values;
  37. if (((bitField & 50397184) === 0)) {
  38. this._promise._setAsyncGuaranteed();
  39. return values._then(
  40. init,
  41. this._reject,
  42. undefined,
  43. this,
  44. resolveValueIfEmpty
  45. );
  46. } else if (((bitField & 33554432) !== 0)) {
  47. values = values._value();
  48. } else if (((bitField & 16777216) !== 0)) {
  49. return this._reject(values._reason());
  50. } else {
  51. return this._cancel();
  52. }
  53. }
  54. values = util.asArray(values);
  55. if (values === null) {
  56. var err = apiRejection(
  57. "expecting an array or an iterable object but got " + util.classString(values)).reason();
  58. this._promise._rejectCallback(err, false);
  59. return;
  60. }
  61. if (values.length === 0) {
  62. if (resolveValueIfEmpty === -5) {
  63. this._resolveEmptyArray();
  64. }
  65. else {
  66. this._resolve(toResolutionValue(resolveValueIfEmpty));
  67. }
  68. return;
  69. }
  70. this._iterate(values);
  71. };
  72. PromiseArray.prototype._iterate = function(values) {
  73. var len = this.getActualLength(values.length);
  74. this._length = len;
  75. this._values = this.shouldCopyValues() ? new Array(len) : this._values;
  76. var result = this._promise;
  77. var isResolved = false;
  78. var bitField = null;
  79. for (var i = 0; i < len; ++i) {
  80. var maybePromise = tryConvertToPromise(values[i], result);
  81. if (maybePromise instanceof Promise) {
  82. maybePromise = maybePromise._target();
  83. bitField = maybePromise._bitField;
  84. } else {
  85. bitField = null;
  86. }
  87. if (isResolved) {
  88. if (bitField !== null) {
  89. maybePromise.suppressUnhandledRejections();
  90. }
  91. } else if (bitField !== null) {
  92. if (((bitField & 50397184) === 0)) {
  93. maybePromise._proxy(this, i);
  94. this._values[i] = maybePromise;
  95. } else if (((bitField & 33554432) !== 0)) {
  96. isResolved = this._promiseFulfilled(maybePromise._value(), i);
  97. } else if (((bitField & 16777216) !== 0)) {
  98. isResolved = this._promiseRejected(maybePromise._reason(), i);
  99. } else {
  100. isResolved = this._promiseCancelled(i);
  101. }
  102. } else {
  103. isResolved = this._promiseFulfilled(maybePromise, i);
  104. }
  105. }
  106. if (!isResolved) result._setAsyncGuaranteed();
  107. };
  108. PromiseArray.prototype._isResolved = function () {
  109. return this._values === null;
  110. };
  111. PromiseArray.prototype._resolve = function (value) {
  112. this._values = null;
  113. this._promise._fulfill(value);
  114. };
  115. PromiseArray.prototype._cancel = function() {
  116. if (this._isResolved() || !this._promise._isCancellable()) return;
  117. this._values = null;
  118. this._promise._cancel();
  119. };
  120. PromiseArray.prototype._reject = function (reason) {
  121. this._values = null;
  122. this._promise._rejectCallback(reason, false);
  123. };
  124. PromiseArray.prototype._promiseFulfilled = function (value, index) {
  125. this._values[index] = value;
  126. var totalResolved = ++this._totalResolved;
  127. if (totalResolved >= this._length) {
  128. this._resolve(this._values);
  129. return true;
  130. }
  131. return false;
  132. };
  133. PromiseArray.prototype._promiseCancelled = function() {
  134. this._cancel();
  135. return true;
  136. };
  137. PromiseArray.prototype._promiseRejected = function (reason) {
  138. this._totalResolved++;
  139. this._reject(reason);
  140. return true;
  141. };
  142. PromiseArray.prototype._resultCancelled = function() {
  143. if (this._isResolved()) return;
  144. var values = this._values;
  145. this._cancel();
  146. if (values instanceof Promise) {
  147. values.cancel();
  148. } else {
  149. for (var i = 0; i < values.length; ++i) {
  150. if (values[i] instanceof Promise) {
  151. values[i].cancel();
  152. }
  153. }
  154. }
  155. };
  156. PromiseArray.prototype.shouldCopyValues = function () {
  157. return true;
  158. };
  159. PromiseArray.prototype.getActualLength = function (len) {
  160. return len;
  161. };
  162. return PromiseArray;
  163. };