promise_array.js 5.1 KB

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