rePromise.js 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. /**
  2. * Promise对象的内部状态
  3. *
  4. * @type {Object}
  5. */
  6. var Status = {
  7. PENDING: 'pending',
  8. FULLFILLED: 'resolved',
  9. REJECTED: 'rejected'
  10. };
  11. function empty() {}
  12. /**
  13. * Promise构造函数
  14. *
  15. * @constructor
  16. * @param {Function} resolver 此Promise对象管理的任务
  17. */
  18. function Promise(resolver) {
  19. // ES6原生的Promise构造函数中,若不通过`new`调用Promise的构造函数,会抛出TypeError异常。此处与其一致
  20. if (!(this instanceof Promise)) {
  21. throw new TypeError('TypeError: undefined is not a promise');
  22. }
  23. // ES6原生的Promise构造函数中,若无作为函数的resolver参数,会抛出TypeError异常。此处与其一致
  24. if (typeof resolver !== 'function') {
  25. throw new TypeError('TypeError: Promise resolver undefined is not a function');
  26. }
  27. /**
  28. * Promise对象内部的状态,初始为`pending`。状态只能由`pending`到`fullfilled`或`rejected`
  29. *
  30. * @type {string}
  31. */
  32. this._status = Status.PENDING;
  33. /**
  34. * Promise对象resolved/rejected后拥有的data/reason
  35. *
  36. * - 此处保存此值是为了当一个Promise对象被resolved或rejected后,继续对其调用`then`添加任务,后续处理仍能获得当前Promise的值
  37. *
  38. * @type {Mixed}
  39. */
  40. this._value;
  41. /**
  42. * 当前Promise被resolved/rejected后,需处理的任务
  43. *
  44. * - 由于同一个Promise对象可以调用多次`then`方法,以添加多个并行任务,所以此处是一个数组
  45. *
  46. * @type {Array.<Function>}
  47. */
  48. this._doneCallbacks = [];
  49. this._failCallbacks = [];
  50. var promise = this;
  51. resolver(
  52. function (data) {
  53. resolve(promise, data);
  54. },
  55. function (reason) {
  56. reject(promise, reason);
  57. }
  58. );
  59. }
  60. Promise.prototype = {
  61. constructor: Promise,
  62. /**
  63. * Promise的`then`方法
  64. *
  65. * @param {Function|Mixed} onResolve 当前Promise对象被resolved后,需处理的任务
  66. * @param {Function|Mixed} onReject 当前Promise对象被rejected后,需处理的任务
  67. * @return {Promise} 返回一个新的Promise对象,用于链式操作
  68. */
  69. then: function (onResolve, onReject) {
  70. var promise = new Promise(empty);
  71. this._doneCallbacks.push(makeCallback(promise, onResolve, 'resolve'));
  72. this._failCallbacks.push(makeCallback(promise, onReject, 'reject'));
  73. // 如果在一个已经被fullfilled或rejected的promise上调用then,则需要直接执行通过then注册的回调函数
  74. run(this);
  75. return promise;
  76. },
  77. /**
  78. * Promise的`done`方法
  79. *
  80. * @param {Function|Mixed} onResolve 当前Promise对象被resolved后,需处理的任务
  81. * @return {Promise} 返回一个新的Promise对象,用于链式操作
  82. */
  83. done: function (onResolve) {
  84. return this.then(onResolve, null);
  85. },
  86. /**
  87. * Promise的`fail`方法
  88. *
  89. * @param {Function|Mixed} onReject 当前Promise对象被rejected后,需处理的任务
  90. * @return {Promise} 返回一个新的Promise对象,用于链式操作
  91. */
  92. fail: function (onReject) {
  93. return this.then(null, onReject);
  94. },
  95. /**
  96. * Promise的`catch`方法
  97. *
  98. * @param {Function|Mixed} onFail 当前Promise对象被rejected后,需处理的任务
  99. * @return {Promise} 返回一个新的Promise对象,用于链式操作
  100. */
  101. catch: function (onFail) {
  102. return this.then(null, onFail);
  103. }
  104. };
  105. /**
  106. * 创建一个Promise对象,并用给定值resolve它
  107. *
  108. * @param {Mixed} value 用于resolve新创建的Promise对象的值
  109. * @return {Promise} 返回一个新的Promise对象,用于链式操作
  110. */
  111. Promise.resolve = function (value) {
  112. var promise = new Promise(empty);
  113. resolve(promise, value);
  114. return promise;
  115. };
  116. /**
  117. * 创建一个Promise对象,并用给定值reject它
  118. *
  119. * @param {Mixed} reason 用于reject新创建的Promise对象的值
  120. * @return {Promise} 返回一个新的Promise对象,用于链式操作
  121. */
  122. Promise.reject = function (reason) {
  123. var promise = new Promise(empty);
  124. reject(promise, reason);
  125. return promise;
  126. };
  127. /**
  128. * 返回一个promise,这个promise在iterable中的任意一个promise被解决或拒绝后,
  129. * 立刻以相同的解决值被解决或以相同的拒绝原因被拒绝
  130. *
  131. * @param {Iterable.<Promise|Mixed>} iterable 一组Promise对象或其它值
  132. * @return {Promise} 返回一个新的Promise对象,用于链式操作
  133. */
  134. Promise.race = function (iterable) {
  135. if (!iterable || !iterable.hasOwnProperty('length')) {
  136. throw new TypeError('TypeError: Parameter `iterable` must be a iterable object');
  137. }
  138. var promise = new Promise(empty);
  139. for (var i = 0, len = iterable.length; i < len; i++) {
  140. var iterate = iterable[i];
  141. if (!(iterate instanceof Promise)) {
  142. iterate = Promise.resolve(iterate);
  143. }
  144. iterate.then(resolveRaceCallback, rejectRaceCallback);
  145. }
  146. var settled = false;
  147. function resolveRaceCallback(data) {
  148. if (settled) {
  149. return;
  150. }
  151. settled = true;
  152. resolve(promise, data);
  153. }
  154. function rejectRaceCallback(reason) {
  155. if (settled) {
  156. return;
  157. }
  158. settled = true;
  159. reject(promise, reason);
  160. }
  161. };
  162. /**
  163. * 返回一个promise,该promise会在iterable参数内的所有promise都被解决后被解决
  164. *
  165. * @param {Iterable.<Promise|Mixed>} iterable 一组Promise对象或其它值
  166. * @return {Promise} 返回一个新的Promise对象,用于链式操作
  167. */
  168. Promise.all = function (iterable) {
  169. if (!iterable || !iterable.hasOwnProperty('length')) {
  170. throw new TypeError('TypeError: Parameter `iterable` must be a iterable object');
  171. }
  172. var promise = new Promise(empty);
  173. var length = iterable.length;
  174. for (var i = 0; i < length; i++) {
  175. var iterate = iterable[i];
  176. if (!(iterate instanceof Promise)) {
  177. iterate = Promise.resolve(iterate);
  178. }
  179. iterate.then(makeAllCallback(iterate, i, 'resolve'), makeAllCallback(iterate, i, 'reject'));
  180. }
  181. var result = [];
  182. var count = 0;
  183. function makeAllCallback(iterate, index, action) {
  184. return function (value) {
  185. if (action === 'reject') {
  186. reject(promise, value);
  187. return;
  188. }
  189. result[index] = value;
  190. if (++count === length) {
  191. resolve(promise, result);
  192. }
  193. }
  194. }
  195. };
  196. /**
  197. * 返回一个Deferred对象,包含一个新创建的Promise对象,以及`resolve`和`reject`方法
  198. *
  199. * @return {Deferred}
  200. */
  201. Promise.defer = function () {
  202. var promise = new Promise(empty);
  203. return {
  204. promise: promise,
  205. resolve: function (data) {
  206. resolve(promise, data);
  207. },
  208. reject: function (reason) {
  209. reject(promise, reason);
  210. }
  211. };
  212. };
  213. function run(promise) {
  214. // `then`方法中也会调用,所以此处仍需做一次判断
  215. if (promise._status === Status.PENDING) {
  216. return;
  217. }
  218. var value = promise._value;
  219. var callbacks = promise._status === Status.FULLFILLED
  220. ? promise._doneCallbacks
  221. : promise._failCallbacks;
  222. // Promise需要异步操作
  223. setTimeout(function () {
  224. for (var i = 0, len = callbacks.length; i < len; i++) {
  225. callbacks[i](value);
  226. }
  227. });
  228. // 每个promise只能被执行一次。虽然`_doneCallbacks`和`_failCallbacks`用户不应该直接访问,
  229. // 但还是可以访问到,保险起见,做清空处理。
  230. promise._doneCallbacks = [];
  231. promise._failCallbacks = [];
  232. }
  233. function resolve(promise, data) {
  234. if (promise._status !== Status.PENDING) {
  235. return;
  236. }
  237. promise._status = Status.FULLFILLED;
  238. promise._value = data;
  239. run(promise);
  240. }
  241. function reject(promise, reason) {
  242. if (promise._status !== Status.PENDING) {
  243. return;
  244. }
  245. promise._status = Status.REJECTED;
  246. promise._value = reason;
  247. run(promise);
  248. }
  249. function makeCallback(promise, callback, action) {
  250. return function promiseCallback(value) {
  251. // 如果传递了callback,则使用前一个promise传递过来的值作为参数调用callback,
  252. // 并根据callback的调用结果来处理当前promise
  253. if (typeof callback === 'function') {
  254. var x;
  255. try {
  256. x = callback(value);
  257. }
  258. catch (e) {
  259. // 如果调用callback时抛出异常,则直接用此异常对象reject当前promise
  260. reject(promise, e);
  261. }
  262. // 如果callback的返回值是当前promise,为避免造成死循环,需要抛出异常
  263. // 根据Promise+规范,此处应抛出TypeError异常
  264. if (x === promise) {
  265. var reason = new TypeError('TypeError: The return value could not be same with the promise');
  266. reject(promise, reason);
  267. }
  268. // 如果返回值是一个Promise对象,则当返回的Promise对象被resolve/reject后,再resolve/reject当前Promise
  269. else if (x instanceof Promise) {
  270. x.then(
  271. function (data) {
  272. resolve(promise, data);
  273. },
  274. function (reason) {
  275. reject(promise, reason);
  276. }
  277. );
  278. }
  279. else {
  280. var then;
  281. (function resolveThenable(x) {
  282. // 如果返回的是一个Thenable对象(此处逻辑有点坑,参照Promise+的规范实现)
  283. if (x && (typeof x === 'object'|| typeof x === 'function')) {
  284. try {
  285. then = x.then;
  286. }
  287. catch (e) {
  288. reject(promise, e);
  289. return;
  290. }
  291. if (typeof then === 'function') {
  292. // 调用Thenable对象的`then`方法时,传递进去的`resolvePromise`和`rejectPromise`方法(及下面的两个匿名方法)
  293. // 可能会被重复调用。但Promise+规范规定这两个方法有且只能有其中的一个被调用一次,多次调用将被忽略。
  294. // 此处通过`invoked`来处理重复调用
  295. var invoked = false;
  296. try {
  297. then.call(
  298. x,
  299. function (y) {
  300. if (invoked) {
  301. return;
  302. }
  303. invoked = true;
  304. // 避免死循环
  305. if (y === x) {
  306. throw new TypeError('TypeError: The return value could not be same with the previous thenable object');
  307. }
  308. // y仍有可能是thenable对象,递归调用
  309. resolveThenable(y);
  310. },
  311. function (e) {
  312. if (invoked) {
  313. return;
  314. }
  315. invoked = true;
  316. reject(promise, e);
  317. }
  318. );
  319. }
  320. catch (e) {
  321. // 如果`resolvePromise`和`rejectPromise`方法被调用后,再抛出异常,则忽略异常
  322. // 否则用异常对象reject此Promise对象
  323. if (!invoked) {
  324. reject(promise, e);
  325. }
  326. }
  327. }
  328. else {
  329. resolve(promise, x);
  330. }
  331. }
  332. else {
  333. resolve(promise, x);
  334. }
  335. }(x));
  336. }
  337. }
  338. // 如果未传递callback,直接用前一个promise传递过来的值resolve/reject当前Promise对象
  339. else {
  340. action === 'resolve'
  341. ? resolve(promise, value)
  342. : reject(promise, value);
  343. }
  344. };
  345. }
  346. module.exports = Promise