1. Promise源码分析

1. Promise三种状态

pending(进行中)、fulfilled(已成功)、rejected(已失败)

2. new Promise()对象参数

是一个回调函数, 该回调函数接受两个参数,分别是成功时的回调resolve和失败时的回
调reject;

  1. resolve的参数除了正常值以外, 还可能是一个Promise对象的实例;
  2. reject的参数通常是一个Error对象的实例;

3. then()方法

返回一个新的Promise实例.
接收两个参数:

  1. onResolved(fulfilled状态的回调);
  2. onRejected(rejected状态的回调,该参数可选)

4.catch()方法

返回一个新的promise对象

5. finally()方法

finally方法不管Promise状态如何都会执行,该方法的回调函数不接受任何参数

6. Promise.all()方法

  1. 将多个Promise实例,包装成一个新的Promise实例
  • 入参: 由Promise对象组
    成的数组作为参数(Promise.all()方法的参数可以不是数组,但必须具有Iterator接口,且返回的每个成员都是
    Promise实例)
  • 注意: 参数中只要有一个实例触发catch方法,都会触发Promise.all()方法返回的新的实例的catch方法

7. Promise.race()方法

  • 入参: 参数与Promise.all方法一样
  • 执行说明: 参数中的实例只要有一个率先改变状态就会将该实例的状态传给Promise.race()方法,并将返回值作为Promise.race()方法产生的Promise实例的返回值

8. Promise.resolve()方法

将现有对象转为Promise对象

  • 如果该方法的参数为一个Promise对象,Promise.resolve()将不做任何处理;
  • 如果参数thenable对象(即具有then方法),Promise.resolve()将该对象转为Promise对象并立即执行then方法;
  • 如果参数是一个原始值,或者是一个不具有then方法的对象,则Promise.resolve方法返回一个新的Promise对象,状态为fulfilled,其参数将会作为then方法中onResolved回调函数的参数.
  • 如果Promise.resolve方法不带参数,会直接返回一个fulfilled状态的 Promise 对象。
  • 需要注意的是,立即resolve()的 Promise 对象,是在本轮“事件循环”(event loop)的结束时执行,而不是在下一轮“事
    件循环”的开始时。

9. Promise.reject()方法

同样返回一个新的Promise对象,状态为rejected,无论传入任何参数都将作为reject()的参数

2. Promise代码实现

  1. // 初始状态
  2. const PENDING = "pending";
  3. // 完成状态
  4. const FULFILLED = "fulfilled";
  5. // 失败状态
  6. const REJECTED = "rejected";
  7. // 异步执行方法封装
  8. function asyncExecFun(fn) {
  9. setTimeout(() => fn(), 0);
  10. }
  11. // 执行promise resolve功能
  12. function resolvePromise(promise, res, resolve, reject) {
  13. // 返回同一个promise
  14. if (promise === res) {
  15. reject(new TypeError("Chaining cycle detected for promise #<MyPromise>"));
  16. return;
  17. }
  18. // promise结果
  19. if (res instanceof MyPromise) {
  20. res.then(resolve, reject);
  21. } else {
  22. // 非promise结果
  23. resolve(res);
  24. }
  25. }
  26. class MyPromise {
  27. status = PENDING;
  28. value = undefined;
  29. reason = undefined;
  30. successCallbacks = [];
  31. failCallbacks = [];
  32. constructor(exector) {
  33. // 立即执行传入参数
  34. // 参数直接写为 this.resolve 会导致函数内 this指向会发生改变
  35. // 异步执行状态变更
  36. // 捕获执行器的异常
  37. try {
  38. exector(
  39. (value) => asyncExecFun(() => this.resolve(value)),
  40. (reason) => asyncExecFun(() => this.reject(reason))
  41. );
  42. } catch (e) {
  43. this.reject(e)
  44. }
  45. }
  46. resolve(value) {
  47. // 如果状态已经变更则直接返回
  48. if (this.status !== PENDING) return;
  49. this.value = value;
  50. this.status = FULFILLED;
  51. // 执行所有成功回调
  52. while (this.successCallbacks.length) this.successCallbacks.shift()();
  53. }
  54. reject(reason) {
  55. // 如果状态已经变更则直接返回
  56. if (this.status !== PENDING) return;
  57. this.reason = reason;
  58. this.status = REJECTED;
  59. if(!this.failCallbacks.length){
  60. throw '(in MyPromise)'
  61. }
  62. // 执行所有失败回调
  63. while (this.failCallbacks.length) this.failCallbacks.shift()();
  64. }
  65. then(successCallback, failCallback) {
  66. // 成功函数处理 忽略函数之外的其他值
  67. successCallback =
  68. typeof successCallback == "function" ? successCallback : (v) => v;
  69. // 失败函数处理 忽略函数之外的其他值 抛出异常 实现catch冒泡的关键
  70. failCallback =
  71. typeof failCallback == "function"
  72. ? failCallback
  73. : (reason) => {
  74. throw reason;
  75. };
  76. let promise = new MyPromise((resolve, reject) => {
  77. // 统一异常处理逻辑
  78. const execFun = (fn, val) => {
  79. try {
  80. let res = fn(val);
  81. resolvePromise(promise, res, resolve, reject);
  82. } catch (e) {
  83. reject(e);
  84. }
  85. };
  86. // 执行成功回调
  87. const execSuccessCallback = () => execFun(successCallback, this.value);
  88. // 执行失败回调
  89. const execFailCallback = () => execFun(failCallback, this.reason);
  90. // 同步将对应成功或者失败回调事件加入对应回调队列
  91. if (this.status === PENDING) {
  92. // 将成功回调加入队列
  93. this.successCallbacks.push(execSuccessCallback);
  94. // 讲失败回调加入队列
  95. this.failCallbacks.push(execFailCallback);
  96. return;
  97. }
  98. // 延迟执行 可以将函数执行结果和当前then 返回的promise 进行比较
  99. asyncExecFun(() => {
  100. // 如果已经 fulfilled 可直接调用成功回调方法
  101. if (this.status === FULFILLED) {
  102. execSuccessCallback();
  103. // 如果已经 rejected 可直接调用失败回调方法
  104. } else if (this.status === REJECTED) {
  105. execFailCallback();
  106. }
  107. });
  108. });
  109. return promise;
  110. }
  111. catch(failCallback) {
  112. return this.then(undefined, failCallback);
  113. }
  114. finally(callback) {
  115. return this.then(
  116. // 穿透正常值
  117. (value) => MyPromise.resolve(callback()).then(() => value),
  118. (reason) =>
  119. MyPromise.resolve(callback()).then(() => {
  120. // 穿透异常信息
  121. throw reason;
  122. })
  123. );
  124. }
  125. static resolve(value) {
  126. // 如果是MyPromise 实例 则直接返回
  127. if (value instanceof MyPromise) return value;
  128. // 如果是MyPromise 实例 否则返回一个 MyPromise实例
  129. return new MyPromise((resolve) => resolve(value));
  130. }
  131. static reject(reason) {
  132. // 如果是MyPromise 实例 则直接返回
  133. if (reason instanceof MyPromise) return reason;
  134. // 如果是MyPromise 实例 否则返回一个 MyPromise实例
  135. return new MyPromise((resolve, reject) => reject(reason));
  136. }
  137. // all方法
  138. static all(array) {
  139. // 存储结果
  140. let result = [];
  141. // 存储数组长度
  142. let len = array.length;
  143. // 创建返回MyPromise
  144. let promise = new MyPromise((resolve, reject) => {
  145. // 定义当前MyPromise的索引
  146. let index = 0;
  147. // 添加数据的公用方法
  148. function addData(key, data) {
  149. // 赋值
  150. result[key] = data;
  151. // 索引递增
  152. index++;
  153. // 全部执行完则resolve
  154. if (index == len) {
  155. resolve(result);
  156. }
  157. }
  158. // 按顺序变量数组
  159. for (let i = 0; i < len; i++) {
  160. let curr = array[i];
  161. // 如果是MyPromise则 按其规则处理
  162. if (curr instanceof MyPromise) {
  163. curr.then((value) => addData(i, value), reject);
  164. } else {
  165. // 非MyPromise直接赋值
  166. addData(i, curr);
  167. }
  168. }
  169. });
  170. // 返回新的MyPromise实例
  171. return promise;
  172. }
  173. // 只要有一个成功或者失败就返回
  174. static race(array) {
  175. let promise = new MyPromise((resolve, reject) => {
  176. for (let i = 0; i < array.length; i++) {
  177. let curr = array[i];
  178. // MyPromise实例 结果处理
  179. if (curr instanceof MyPromise) {
  180. curr.then(resolve, reject);
  181. } else {
  182. // 非MyPromise实例处理
  183. resolve(curr);
  184. }
  185. }
  186. });
  187. return promise;
  188. }
  189. }
  190. module.exports = MyPromise;

3. Promise优缺点

1. Promise优点

  1. 统一异步API: 逐渐被用作浏览器的异步API, 统一现在各种各样的API
  2. Promise与事件对比: ?
  3. Promise与回调对比: 解决了回调地狱的问题, 将异步操作与同步操作的流程表达处理
  4. Promise可以链式调用, 更好的错误处理方式(包含了异常处理)

    2. Promise缺点

  5. 无法取消Promise, 一单建立就会立即执行, 无法中途取消.

  6. 如果不设置回调函数, Promise内部抛出的错误不会反应到外部.
  7. 当处于pending状态的时候,无法知道目前进展到哪一个阶段(刚开始还是即将完成).