join.js 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. "use strict";
  2. module.exports =
  3. function(Promise, PromiseArray, tryConvertToPromise, INTERNAL) {
  4. var util = require("./util.js");
  5. var canEvaluate = util.canEvaluate;
  6. var tryCatch = util.tryCatch;
  7. var errorObj = util.errorObj;
  8. var reject;
  9. if (!false) {
  10. if (canEvaluate) {
  11. var thenCallback = function(i) {
  12. return new Function("value", "holder", " \n\
  13. 'use strict'; \n\
  14. holder.pIndex = value; \n\
  15. holder.checkFulfillment(this); \n\
  16. ".replace(/Index/g, i));
  17. };
  18. var caller = function(count) {
  19. var values = [];
  20. for (var i = 1; i <= count; ++i) values.push("holder.p" + i);
  21. return new Function("holder", " \n\
  22. 'use strict'; \n\
  23. var callback = holder.fn; \n\
  24. return callback(values); \n\
  25. ".replace(/values/g, values.join(", ")));
  26. };
  27. var thenCallbacks = [];
  28. var callers = [undefined];
  29. for (var i = 1; i <= 5; ++i) {
  30. thenCallbacks.push(thenCallback(i));
  31. callers.push(caller(i));
  32. }
  33. var Holder = function(total, fn) {
  34. this.p1 = this.p2 = this.p3 = this.p4 = this.p5 = null;
  35. this.fn = fn;
  36. this.total = total;
  37. this.now = 0;
  38. };
  39. Holder.prototype.callers = callers;
  40. Holder.prototype.checkFulfillment = function(promise) {
  41. var now = this.now;
  42. now++;
  43. var total = this.total;
  44. if (now >= total) {
  45. var handler = this.callers[total];
  46. promise._pushContext();
  47. var ret = tryCatch(handler)(this);
  48. promise._popContext();
  49. if (ret === errorObj) {
  50. promise._rejectCallback(ret.e, false, true);
  51. } else {
  52. promise._resolveCallback(ret);
  53. }
  54. } else {
  55. this.now = now;
  56. }
  57. };
  58. var reject = function (reason) {
  59. this._reject(reason);
  60. };
  61. }
  62. }
  63. Promise.join = function () {
  64. var last = arguments.length - 1;
  65. var fn;
  66. if (last > 0 && typeof arguments[last] === "function") {
  67. fn = arguments[last];
  68. if (!false) {
  69. if (last < 6 && canEvaluate) {
  70. var ret = new Promise(INTERNAL);
  71. ret._captureStackTrace();
  72. var holder = new Holder(last, fn);
  73. var callbacks = thenCallbacks;
  74. for (var i = 0; i < last; ++i) {
  75. var maybePromise = tryConvertToPromise(arguments[i], ret);
  76. if (maybePromise instanceof Promise) {
  77. maybePromise = maybePromise._target();
  78. if (maybePromise._isPending()) {
  79. maybePromise._then(callbacks[i], reject,
  80. undefined, ret, holder);
  81. } else if (maybePromise._isFulfilled()) {
  82. callbacks[i].call(ret,
  83. maybePromise._value(), holder);
  84. } else {
  85. ret._reject(maybePromise._reason());
  86. }
  87. } else {
  88. callbacks[i].call(ret, maybePromise, holder);
  89. }
  90. }
  91. return ret;
  92. }
  93. }
  94. }
  95. var $_len = arguments.length;var args = new Array($_len); for(var $_i = 0; $_i < $_len; ++$_i) {args[$_i] = arguments[$_i];}
  96. if (fn) args.pop();
  97. var ret = new PromiseArray(args).promise();
  98. return fn !== undefined ? ret.spread(fn) : ret;
  99. };
  100. };