promise_array.js 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. "use strict";
  2. module.exports = function(Promise, INTERNAL, tryConvertToPromise,
  3. apiRejection) {
  4. var util = require("./util.js");
  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. var parent;
  15. if (values instanceof Promise) {
  16. parent = values;
  17. promise._propagateFrom(parent, 1 | 4);
  18. }
  19. this._values = values;
  20. this._length = 0;
  21. this._totalResolved = 0;
  22. this._init(undefined, -2);
  23. }
  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. this._values = values;
  35. if (values._isFulfilled()) {
  36. values = values._value();
  37. if (!isArray(values)) {
  38. var err = new Promise.TypeError("expecting an array, a promise or a thenable\u000a\u000a See http://goo.gl/s8MMhc\u000a");
  39. this.__hardReject__(err);
  40. return;
  41. }
  42. } else if (values._isPending()) {
  43. values._then(
  44. init,
  45. this._reject,
  46. undefined,
  47. this,
  48. resolveValueIfEmpty
  49. );
  50. return;
  51. } else {
  52. this._reject(values._reason());
  53. return;
  54. }
  55. } else if (!isArray(values)) {
  56. this._promise._reject(apiRejection("expecting an array, a promise or a thenable\u000a\u000a See http://goo.gl/s8MMhc\u000a")._reason());
  57. return;
  58. }
  59. if (values.length === 0) {
  60. if (resolveValueIfEmpty === -5) {
  61. this._resolveEmptyArray();
  62. }
  63. else {
  64. this._resolve(toResolutionValue(resolveValueIfEmpty));
  65. }
  66. return;
  67. }
  68. var len = this.getActualLength(values.length);
  69. this._length = len;
  70. this._values = this.shouldCopyValues() ? new Array(len) : this._values;
  71. var promise = this._promise;
  72. for (var i = 0; i < len; ++i) {
  73. var isResolved = this._isResolved();
  74. var maybePromise = tryConvertToPromise(values[i], promise);
  75. if (maybePromise instanceof Promise) {
  76. maybePromise = maybePromise._target();
  77. if (isResolved) {
  78. maybePromise._unsetRejectionIsUnhandled();
  79. } else if (maybePromise._isPending()) {
  80. maybePromise._proxyPromiseArray(this, i);
  81. } else if (maybePromise._isFulfilled()) {
  82. this._promiseFulfilled(maybePromise._value(), i);
  83. } else {
  84. this._promiseRejected(maybePromise._reason(), i);
  85. }
  86. } else if (!isResolved) {
  87. this._promiseFulfilled(maybePromise, i);
  88. }
  89. }
  90. };
  91. PromiseArray.prototype._isResolved = function () {
  92. return this._values === null;
  93. };
  94. PromiseArray.prototype._resolve = function (value) {
  95. this._values = null;
  96. this._promise._fulfill(value);
  97. };
  98. PromiseArray.prototype.__hardReject__ =
  99. PromiseArray.prototype._reject = function (reason) {
  100. this._values = null;
  101. this._promise._rejectCallback(reason, false, true);
  102. };
  103. PromiseArray.prototype._promiseProgressed = function (progressValue, index) {
  104. this._promise._progress({
  105. index: index,
  106. value: progressValue
  107. });
  108. };
  109. PromiseArray.prototype._promiseFulfilled = function (value, index) {
  110. this._values[index] = value;
  111. var totalResolved = ++this._totalResolved;
  112. if (totalResolved >= this._length) {
  113. this._resolve(this._values);
  114. }
  115. };
  116. PromiseArray.prototype._promiseRejected = function (reason, index) {
  117. this._totalResolved++;
  118. this._reject(reason);
  119. };
  120. PromiseArray.prototype.shouldCopyValues = function () {
  121. return true;
  122. };
  123. PromiseArray.prototype.getActualLength = function (len) {
  124. return len;
  125. };
  126. return PromiseArray;
  127. };