es6-extensions.js 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. 'use strict';
  2. //This file contains the ES6 extensions to the core Promises/A+ API
  3. var Promise = require('./core.js');
  4. module.exports = Promise;
  5. /* Static Functions */
  6. var TRUE = valuePromise(true);
  7. var FALSE = valuePromise(false);
  8. var NULL = valuePromise(null);
  9. var UNDEFINED = valuePromise(undefined);
  10. var ZERO = valuePromise(0);
  11. var EMPTYSTRING = valuePromise('');
  12. function valuePromise(value) {
  13. var p = new Promise(Promise._D);
  14. p._y = 1;
  15. p._z = value;
  16. return p;
  17. }
  18. Promise.resolve = function (value) {
  19. if (value instanceof Promise) return value;
  20. if (value === null) return NULL;
  21. if (value === undefined) return UNDEFINED;
  22. if (value === true) return TRUE;
  23. if (value === false) return FALSE;
  24. if (value === 0) return ZERO;
  25. if (value === '') return EMPTYSTRING;
  26. if (typeof value === 'object' || typeof value === 'function') {
  27. try {
  28. var then = value.then;
  29. if (typeof then === 'function') {
  30. return new Promise(then.bind(value));
  31. }
  32. } catch (ex) {
  33. return new Promise(function (resolve, reject) {
  34. reject(ex);
  35. });
  36. }
  37. }
  38. return valuePromise(value);
  39. };
  40. var iterableToArray = function (iterable) {
  41. if (typeof Array.from === 'function') {
  42. // ES2015+, iterables exist
  43. iterableToArray = Array.from;
  44. return Array.from(iterable);
  45. }
  46. // ES5, only arrays and array-likes exist
  47. iterableToArray = function (x) { return Array.prototype.slice.call(x); };
  48. return Array.prototype.slice.call(iterable);
  49. }
  50. Promise.all = function (arr) {
  51. var args = iterableToArray(arr);
  52. return new Promise(function (resolve, reject) {
  53. if (args.length === 0) return resolve([]);
  54. var remaining = args.length;
  55. function res(i, val) {
  56. if (val && (typeof val === 'object' || typeof val === 'function')) {
  57. if (val instanceof Promise && val.then === Promise.prototype.then) {
  58. while (val._y === 3) {
  59. val = val._z;
  60. }
  61. if (val._y === 1) return res(i, val._z);
  62. if (val._y === 2) reject(val._z);
  63. val.then(function (val) {
  64. res(i, val);
  65. }, reject);
  66. return;
  67. } else {
  68. var then = val.then;
  69. if (typeof then === 'function') {
  70. var p = new Promise(then.bind(val));
  71. p.then(function (val) {
  72. res(i, val);
  73. }, reject);
  74. return;
  75. }
  76. }
  77. }
  78. args[i] = val;
  79. if (--remaining === 0) {
  80. resolve(args);
  81. }
  82. }
  83. for (var i = 0; i < args.length; i++) {
  84. res(i, args[i]);
  85. }
  86. });
  87. };
  88. function onSettledFulfill(value) {
  89. return { status: 'fulfilled', value: value };
  90. }
  91. function onSettledReject(reason) {
  92. return { status: 'rejected', reason: reason };
  93. }
  94. function mapAllSettled(item) {
  95. if(item && (typeof item === 'object' || typeof item === 'function')){
  96. if(item instanceof Promise && item.then === Promise.prototype.then){
  97. return item.then(onSettledFulfill, onSettledReject);
  98. }
  99. var then = item.then;
  100. if (typeof then === 'function') {
  101. return new Promise(then.bind(item)).then(onSettledFulfill, onSettledReject)
  102. }
  103. }
  104. return onSettledFulfill(item);
  105. }
  106. Promise.allSettled = function (iterable) {
  107. return Promise.all(iterableToArray(iterable).map(mapAllSettled));
  108. };
  109. Promise.reject = function (value) {
  110. return new Promise(function (resolve, reject) {
  111. reject(value);
  112. });
  113. };
  114. Promise.race = function (values) {
  115. return new Promise(function (resolve, reject) {
  116. iterableToArray(values).forEach(function(value){
  117. Promise.resolve(value).then(resolve, reject);
  118. });
  119. });
  120. };
  121. /* Prototype Methods */
  122. Promise.prototype['catch'] = function (onRejected) {
  123. return this.then(null, onRejected);
  124. };
  125. function getAggregateError(errors){
  126. if(typeof AggregateError === 'function'){
  127. return new AggregateError(errors,'All promises were rejected');
  128. }
  129. var error = new Error('All promises were rejected');
  130. error.name = 'AggregateError';
  131. error.errors = errors;
  132. return error;
  133. }
  134. Promise.any = function promiseAny(values) {
  135. return new Promise(function(resolve, reject) {
  136. var promises = iterableToArray(values);
  137. var hasResolved = false;
  138. var rejectionReasons = [];
  139. function resolveOnce(value) {
  140. if (!hasResolved) {
  141. hasResolved = true;
  142. resolve(value);
  143. }
  144. }
  145. function rejectionCheck(reason) {
  146. rejectionReasons.push(reason);
  147. if (rejectionReasons.length === promises.length) {
  148. reject(getAggregateError(rejectionReasons));
  149. }
  150. }
  151. if(promises.length === 0){
  152. reject(getAggregateError(rejectionReasons));
  153. } else {
  154. promises.forEach(function(value){
  155. Promise.resolve(value).then(resolveOnce, rejectionCheck);
  156. });
  157. }
  158. });
  159. };