为了能够更好的理解和使用promise,我觉得还是得看一看源码,了解其内部的核心机制 由于Promise内容过多,下面我们由浅入深,一点一点的实现。 本篇篇幅很长,因为我也是一点点写的,要是直接全部写完的代码扔上来,我也看得晕,哈哈加油吧,慢慢看

1.声明Promise并绑定this

  1. let p = new PromiseA((resolve, reject) => {
  2. resolve("成功");
  3. // reject("失败");
  4. });
  5. console.log(p);

(1)声明

首先,我们声明一个 PromiseA 来代表我们自己写的promise

我们知道,promise的特性: (1)有三个状态pending,fulfilled,rejected (2)状态一旦改变,后续状态不可改变 定义时,传入一个参数为 resolve 和 rejected 的函数 executor

  1. class PromiseA {
  2. static PENDING = "pending";
  3. static FULFILLED = "fulfilled";
  4. static REJECTED = "rejected";
  5. // 按照定义,我们写出promise
  6. constructor(executor) {
  7. this.status = PromiseA.PENDING;
  8. this.value = null;
  9. // 先不绑定,看看效果
  10. executor(this.resolve, this.reject);
  11. }
  12. // 由于resolve和reject执行时是在promise外部,隐式传递导致this丢失,所以需要另外绑定
  13. resolve(value) {
  14. this.status = PromiseA.FULFILLED;
  15. this.value = value;
  16. }
  17. reject(reason) {
  18. this.status = PromiseA.REJECTED;
  19. this.value = reason;
  20. }
  21. }

image.png

resolve和reject不绑定this,就会出现这样的报错,找不到this的status

(2)绑定this 和 保护状态

  1. class PromiseA {
  2. static PENDING = "pending";
  3. static FULFILLED = "fulfilled";
  4. static REJECTED = "rejected";
  5. constructor(executor) {
  6. this.status = PromiseA.PENDING;
  7. this.value = null;
  8. // 绑定this
  9. executor(this.resolve.bind(this), this.reject.bind(this));
  10. }
  11. resolve(value) {
  12. // 判断一下,如果状态不是pending那么状态以及改变,不能再次改变
  13. if (this.status === PromiseA.PENDING) {
  14. this.status = PromiseA.FULFILLED;
  15. this.value = value;
  16. }
  17. }
  18. reject(reason) {
  19. if (this.status === PromiseA.PENDING) {
  20. this.status = PromiseA.REJECTED;
  21. this.value = reason;
  22. }
  23. }
  24. }

image.png成功打印

(3)定义时的错误处理

我们知道,如果我们在定义promise时,在状态改变之前出现了错误,这个promise会之间变成reject状态

  1. let p = new Promise((resolve,reject)=>{
  2. console.log(abc); // abc未定义,状态变成rejected
  3. resolve("原生成功")
  4. })
  5. console.log(p);

image.png

  1. let p = new PromiseA((resolve, reject) => {
  2. console.log(abc);
  3. resolve("成功");
  4. });
  5. console.log(p);

image.png
别说状态改变了,后面的代码都执行不了,所以,我们不能因为promise的错误就中断所有代码的执行

  1. class PromiseA {
  2. static PENDING = "pending";
  3. static FULFILLED = "fulfilled";
  4. static REJECTED = "rejected";
  5. constructor(executor) {
  6. this.status = PromiseA.PENDING;
  7. this.value = null;
  8. // try catch 捕捉异常
  9. try {
  10. executor(this.resolve.bind(this), this.reject.bind(this));
  11. } catch (error) {
  12. this.reject(error)
  13. }
  14. }
  15. resolve(value) {
  16. if (this.status === PromiseA.PENDING) {
  17. this.status = PromiseA.FULFILLED;
  18. this.value = value;
  19. }
  20. }
  21. reject(reason) {
  22. if (this.status === PromiseA.PENDING) {
  23. this.status = PromiseA.REJECTED;
  24. this.value = reason;
  25. }
  26. }
  27. }

image.png最后成功执行

2.then方法的基本构建

我们知道then方法有两个参数 onFulfilled 和 onRejected 两个函数 (1)当我们resolve时,then触发onFulfilled (2)当我们reject时,then触发onRejected (3)当 resolve 或 reject 被异步操作延迟时,也就是状态为pending时,then的内部处理 (4)重点:then方法会将onFulfilled 或 onRejected 内产生的错误传递给下一个then或者catch,由于这还没有到链式传递那块,先用try catch代替 (5)then内部执行的函数是异步回调,是异步操作!! (6)还有一个就是我们最容易忽略的点,当 resolve 或 reject 被异步操作延迟时,resolve 或 reject后面的代码应该是同步的,先执行,而不应该是我们then执行完后再执行

(1)构建then

  1. class PromiseA {
  2. // ...上面的代码
  3. then(onFulfilled, onRejected) {
  4. // 防止then中传入的参数为空时报错
  5. if (typeof onFulfilled !== "function") {
  6. onFulfilled = () => { };
  7. }
  8. if (typeof onRejected !== "function") {
  9. onRejected = () => { };
  10. }
  11. if (this.status === PromiseA.FULFILLED) {
  12. // 直接执行的话就是同步了,使用setTimeOut,变成异步
  13. setTimeout(() => {
  14. // 我们知道promise内部会将错误传递给下一个then,或者catch处理
  15. // 我们这里就先用trycatch处理来模仿一下
  16. try {
  17. onFulfilled(this.value);
  18. } catch (error) {
  19. onRejected(error);
  20. }
  21. });
  22. }
  23. if (this.status === PromiseA.REJECTED) {
  24. setTimeout(() => {
  25. try {
  26. onRejected(this.value);
  27. } catch (error) {
  28. onRejected(error);
  29. }
  30. });
  31. }
  32. }
  33. }
  1. let p = new PromiseA((resolve, reject) => {
  2. resolve("成功");
  3. });
  4. p.then(value => {
  5. // 当发送错误时,直接catch到error那处理
  6. // console.log(abc);
  7. console.log("value:", value);
  8. }, error => {
  9. console.log("error:", error);
  10. })
  11. console.log(p);

image.png
image.png

(2)当状态为pending时,then的处理

当状态为 pending 时,这时候我们的resolve或reject八成是被套在了定时器里变异步了

如果我们不对pending状态进行处理,那么我们写的promise.then就无法处理

  1. let p = new PromiseA((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve("成功");
  4. });
  5. });
  6. p.then(value => {
  7. console.log("value:", value);
  8. }, error => {
  9. console.log("error:", error);
  10. });
  11. console.log(p);

image.png

(1)使用callback数组处理 和 错误处理

那我们该如何处理pending状态时的then呢?又要如何拿到异步处理完成后,变化的状态呢? (1)其实,我们可以在构造函数内,新增一个 callbacks 数组(队列) 来存储我们未执行的onFulfilled和onRejected (2)然后,当异步任务完成时,触发resolve或reject,我们再通过resolve和reject内部来触发callback,这样我们就能够实现一个 延时状态改变了 (3)当然,在pending状态内部,我们也还是要进行错误的处理

  1. class PromiseA {
  2. //...静态属性
  3. constructor(executor) {
  4. // ... status, value
  5. this.callbacks = [];
  6. // ...executor
  7. }
  8. resolve(value) {
  9. if (this.status === PromiseA.PENDING) {
  10. this.status = PromiseA.FULFILLED;
  11. this.value = value;
  12. // 当异步任务结束,触发resolve状态改变时,调用callback
  13. this.callbacks.map(callback => {
  14. // 上面说的错误问题依然存在,所以要用try-catch捕获
  15. try {
  16. callback.onFulfilled(this.value);
  17. } catch (error) {
  18. callback.onRejected(error);
  19. }
  20. });
  21. }
  22. }
  23. reject(reason) {
  24. if (this.status === PromiseA.PENDING) {
  25. this.status = PromiseA.REJECTED;
  26. this.value = reason;
  27. this.callbacks.map(callback => {
  28. try {
  29. callback.onRejected(this.value);
  30. } catch (error) {
  31. callback.onRejected(error);
  32. }
  33. });
  34. }
  35. }
  36. then(onFulfilled, onRejected) {
  37. if (typeof onFulfilled !== "function") {
  38. onFulfilled = () => { };
  39. }
  40. if (typeof onRejected !== "function") {
  41. onRejected = () => { };
  42. }
  43. if (this.status === PromiseA.PENDING) {
  44. // 当状态为pending,我们把没有执行的onFulfilled和onRejected存储起来
  45. // 等待状态的改变再来调用
  46. this.callbacks.push({
  47. onFulfilled,
  48. onRejected
  49. });
  50. }
  51. if (this.status === PromiseA.FULFILLED) {
  52. setTimeout(() => {
  53. try {
  54. onFulfilled(this.value);
  55. } catch (error) {
  56. onRejected(error);
  57. }
  58. });
  59. }
  60. if (this.status === PromiseA.REJECTED) {
  61. setTimeout(() => {
  62. try {
  63. onRejected(this.value);
  64. } catch (error) {
  65. onRejected(error);
  66. }
  67. });
  68. }
  69. }
  70. }

此时,我们那刚刚的test再次测试一下
image.png成功的输出了

(2)resolve和reject后方代码的同步执行问题

如何解决这个问题: 其实我们只需要把callback执行时,把callback变成异步执行就行,这样resolve后面的代码就能先执行了

上面代码写完了之后,看似没有什么问题,但实际上,我们在resolve后面添加一个行代码就能发现问题了

  1. let p = new PromiseA((resolve, reject) => {
  2. setTimeout(() => {
  3. resolve("成功");
  4. console.log("666");
  5. });
  6. });
  7. p.then(value => {
  8. console.log("value:", value);
  9. }, error => {
  10. console.log("error:", error);
  11. });
  12. console.log(p);

image.png
666竟然在then执行完之后才输出,这就很不应该了,它应该是在then执行之前输出的

  1. class PromiseA {
  2. // ...
  3. constructor(executor) {...}
  4. resolve(value) {
  5. if (this.status === PromiseA.PENDING) {
  6. this.status = PromiseA.FULFILLED;
  7. this.value = value;
  8. // callback变成异步执行,这样resolve后方的代码就能先执行了
  9. setTimeout(() => {
  10. this.callbacks.map(callback => {
  11. try {
  12. callback.onFulfilled(this.value);
  13. } catch (error) {
  14. callback.onRejected(error);
  15. }
  16. });
  17. });
  18. }
  19. }
  20. reject(reason) {
  21. if (this.status === PromiseA.PENDING) {
  22. this.status = PromiseA.REJECTED;
  23. this.value = reason;
  24. setTimeout(() => {
  25. this.callbacks.map(callback => {
  26. try {
  27. callback.onRejected(this.value);
  28. } catch (error) {
  29. callback.onRejected(error);
  30. }
  31. });
  32. });
  33. }
  34. }
  35. then(onFulfilled, onRejected) {...}
  36. }

3.then的链式传递的实现

链式操作其实也就是我们把 onFulfilled 和 onRejected 执行后的结果封装成一个新的promise传给下一个then而已。 (1)把 onFulfilled 和 onRejected 执行后的返回值封装成一个新的promise(resolve,reject) (2)返回值为普通值,直接resolve 或 reject (3)返回值为promise,获得其内部resolve或reject的值,并通过resolve 或 reject传递 (4)注意其内部可能产生的错误,并通过trycatch进行错误处理,完成错误的链式传递 注意: 返回值为promise时,内部的resolve或reject被延迟执行,和上面的情况类似,但实际上,我们上面的步骤就已经帮我们全部处理完了,由于我们是通过调用返回值promise的 then来实现参数传递的,因为返回值为promise,所以我们上面封装的它也有效。(嘿嘿,所以我们不用考虑这个了)

(1)返回值的封装

封装时,要考虑上面说的,返回值为普通值时,和返回值为promise时的情况

  1. class PromiseA {
  2. static PENDING = "pending";
  3. static FULFILLED = "fulfilled";
  4. static REJECTED = "rejected";
  5. constructor(executor) {
  6. this.status = PromiseA.PENDING;
  7. this.value = null;
  8. this.callbacks = [];
  9. try {
  10. executor(this.resolve.bind(this), this.reject.bind(this));
  11. } catch (error) {
  12. this.reject(error);
  13. }
  14. }
  15. resolve(value) {
  16. if (this.status === PromiseA.PENDING) {
  17. this.status = PromiseA.FULFILLED;
  18. this.value = value;
  19. setTimeout(() => {
  20. this.callbacks.map(callback => {
  21. try {
  22. callback.onFulfilled(this.value);
  23. } catch (error) {
  24. callback.onRejected(error);
  25. }
  26. });
  27. });
  28. }
  29. }
  30. reject(reason) {
  31. if (this.status === PromiseA.PENDING) {
  32. this.status = PromiseA.REJECTED;
  33. this.value = reason;
  34. setTimeout(() => {
  35. this.callbacks.map(callback => {
  36. try {
  37. callback.onRejected(this.value);
  38. } catch (error) {
  39. callback.onRejected(error);
  40. }
  41. });
  42. });
  43. }
  44. }
  45. then(onFulfilled, onRejected) {
  46. if (typeof onFulfilled !== "function") {
  47. onFulfilled = () => { };
  48. }
  49. if (typeof onRejected !== "function") {
  50. onRejected = () => { };
  51. }
  52. if (this.status === PromiseA.PENDING) {
  53. this.callbacks.push({
  54. onFulfilled,
  55. onRejected
  56. });
  57. }
  58. if (this.status === PromiseA.FULFILLED) {
  59. return new PromiseA((resolve, reject) => {
  60. setTimeout(() => {
  61. try {
  62. let res = onFulfilled(this.value);
  63. if (res instanceof PromiseA) {
  64. // 如果返回值是 一个promise,则直接调用其then函数
  65. // 并且把 我们的resolve传入,当作onFulfilled函数来接收其内部resolve的值
  66. res.then(resolve, reject);
  67. } else {
  68. // 返回值为普通值,则直接resolve
  69. resolve(res);
  70. }
  71. } catch (error) {
  72. // onRejected(error);
  73. // 错误处理也交给这个新的promise处理,这样就完成了错误的链式传递
  74. reject(error);
  75. }
  76. });
  77. });
  78. }
  79. if (this.status === PromiseA.REJECTED) {
  80. return new PromiseA((resolve, reject) => {
  81. setTimeout(() => {
  82. try {
  83. let res = onRejected(this.value);
  84. if (res instanceof PromiseA) {
  85. res.then(resolve, reject);
  86. } else {
  87. reject(res);
  88. }
  89. } catch (error) {
  90. reject(error);
  91. }
  92. });
  93. });
  94. }
  95. }
  96. }
  1. // test1
  2. let p = new PromiseA((resolve, reject) => {
  3. resolve("成功");
  4. });
  5. p.then(value => {
  6. console.log("value:", value);
  7. return new PromiseA(resolve => {
  8. resolve("666");
  9. setTimeout(() => {
  10. resolve("666");
  11. });
  12. });
  13. }, error => {
  14. console.log("error:", error);
  15. }).then(value => {
  16. console.log(value);
  17. })
  18. // test2
  19. let p = new PromiseA((resolve, reject) => {
  20. resolve("成功");
  21. });
  22. p.then(value => {
  23. console.log("value:", value);
  24. return new PromiseA(resolve => {
  25. // resolve被延迟时
  26. setTimeout(() => {
  27. resolve("666");
  28. });
  29. });
  30. }, error => {
  31. console.log("error:", error);
  32. }).then(value => {
  33. console.log(value);
  34. })

image.png两次test结果一样,封装成功

  1. let p = new PromiseA((resolve, reject) => {
  2. resolve("成功");
  3. });
  4. p.then(value => {
  5. // 测试错误的链式传递
  6. console.log(abc);
  7. console.log("value:", value);
  8. }, error => {
  9. console.log("error第一次:", error);
  10. }).then(value => {
  11. console.log(value);
  12. }, error => {
  13. console.log("error第二次:", error);
  14. })

image.png成功把错误传给了下一个then

4.静态方法resolve和reject的构建

到这,我们已经实现了promise的大量功能了 这两个静态方法实际上就是调用我们上面写的就行了,会写then了,这两个就很简单了

实际上,Promise.resolve就直接创建一个新的promise,然后resolve就行 (1)Promise.resolve传入值为普通值 (2)Promise.resolve传入值为promise对象

  1. class PromiseA {
  2. static PENDING = "pending";
  3. static FULFILLED = "fulfilled";
  4. static REJECTED = "rejected";
  5. constructor(executor) {
  6. this.status = PromiseA.PENDING;
  7. this.value = null;
  8. this.callbacks = [];
  9. try {
  10. executor(this.resolve.bind(this), this.reject.bind(this));
  11. } catch (error) {
  12. this.reject(error);
  13. }
  14. }
  15. resolve(value) {
  16. if (this.status === PromiseA.PENDING) {
  17. this.status = PromiseA.FULFILLED;
  18. this.value = value;
  19. setTimeout(() => {
  20. this.callbacks.map(callback => {
  21. try {
  22. callback.onFulfilled(this.value);
  23. } catch (error) {
  24. callback.onRejected(error);
  25. }
  26. });
  27. });
  28. }
  29. }
  30. reject(reason) {
  31. if (this.status === PromiseA.PENDING) {
  32. this.status = PromiseA.REJECTED;
  33. this.value = reason;
  34. setTimeout(() => {
  35. this.callbacks.map(callback => {
  36. try {
  37. callback.onRejected(this.value);
  38. } catch (error) {
  39. callback.onRejected(error);
  40. }
  41. });
  42. });
  43. }
  44. }
  45. then(onFulfilled, onRejected) {
  46. // 防止then中传入的参数为空时报错
  47. if (typeof onFulfilled !== "function") {
  48. onFulfilled = () => { };
  49. }
  50. if (typeof onRejected !== "function") {
  51. onRejected = () => { };
  52. }
  53. if (this.status === PromiseA.PENDING) {
  54. this.callbacks.push({
  55. onFulfilled,
  56. onRejected
  57. });
  58. }
  59. if (this.status === PromiseA.FULFILLED) {
  60. return new PromiseA((resolve, reject) => {
  61. setTimeout(() => {
  62. try {
  63. let res = onFulfilled(this.value);
  64. if (res instanceof PromiseA) {
  65. res.then(resolve, reject);
  66. } else {
  67. resolve(res);
  68. }
  69. } catch (error) {
  70. reject(error);
  71. }
  72. });
  73. });
  74. }
  75. if (this.status === PromiseA.REJECTED) {
  76. return new PromiseA((resolve, reject) => {
  77. setTimeout(() => {
  78. try {
  79. let res = onRejected(this.value);
  80. if (res instanceof PromiseA) {
  81. res.then(resolve, reject);
  82. } else {
  83. reject(res);
  84. }
  85. } catch (error) {
  86. reject(error);
  87. }
  88. });
  89. });
  90. }
  91. }
  92. static resolve(value) {
  93. return new PromiseA((resolve, reject) => {
  94. if (value instanceof PromiseA) {
  95. value.then(resolve, reject);
  96. } else {
  97. resolve(value);
  98. }
  99. });
  100. }
  101. static reject(reason) {
  102. return new PromiseA((resolve, reject) => {
  103. if (reason instanceof PromiseA) {
  104. reason.then(resolve, reject);
  105. } else {
  106. reject(reason);
  107. }
  108. });
  109. }
  110. }
  1. // 传入的值为普通值
  2. PromiseA.resolve(666).then(value => {
  3. console.log("resolve:", value);
  4. }, error => {
  5. console.log("reject:", error);
  6. })
  7. PromiseA.reject(666).then(value => {
  8. console.log("resolve:", value);
  9. }, error => {
  10. console.log("reject:", error);
  11. })

image.png

  1. // 传入的值为promise对象
  2. let p = new PromiseA((resolve, reject) => {
  3. resolve("成功");
  4. // reject("失败");
  5. });
  6. PromiseA.resolve(p).then(value => {
  7. console.log("resolve:", value);
  8. }, error => {
  9. console.log("reject:", error);
  10. });
  11. PromiseA.reject(p).then(value => {
  12. console.log("resolve:", value);
  13. }, error => {
  14. console.log("reject:", error);
  15. })

image.png

5.完整核心代码:

  1. class PromiseA {
  2. static PENDING = "pending";
  3. static FULFILLED = "fulfilled";
  4. static REJECTED = "rejected";
  5. constructor(executor) {
  6. this.status = PromiseA.PENDING;
  7. this.value = null;
  8. this.callbacks = [];
  9. try {
  10. executor(this.resolve.bind(this), this.reject.bind(this));
  11. } catch (error) {
  12. this.reject(error);
  13. }
  14. }
  15. resolve(value) {
  16. if (this.status === PromiseA.PENDING) {
  17. this.status = PromiseA.FULFILLED;
  18. this.value = value;
  19. setTimeout(() => {
  20. this.callbacks.map(callback => {
  21. try {
  22. callback.onFulfilled(this.value);
  23. } catch (error) {
  24. callback.onRejected(error);
  25. }
  26. });
  27. });
  28. }
  29. }
  30. reject(reason) {
  31. if (this.status === PromiseA.PENDING) {
  32. this.status = PromiseA.REJECTED;
  33. this.value = reason;
  34. setTimeout(() => {
  35. this.callbacks.map(callback => {
  36. try {
  37. callback.onRejected(this.value);
  38. } catch (error) {
  39. callback.onRejected(error);
  40. }
  41. });
  42. });
  43. }
  44. }
  45. then(onFulfilled, onRejected) {
  46. // 防止then中传入的参数为空时报错
  47. if (typeof onFulfilled !== "function") {
  48. onFulfilled = () => { };
  49. }
  50. if (typeof onRejected !== "function") {
  51. onRejected = () => { };
  52. }
  53. if (this.status === PromiseA.PENDING) {
  54. this.callbacks.push({
  55. onFulfilled,
  56. onRejected
  57. });
  58. }
  59. if (this.status === PromiseA.FULFILLED) {
  60. return new PromiseA((resolve, reject) => {
  61. setTimeout(() => {
  62. try {
  63. let res = onFulfilled(this.value);
  64. if (res instanceof PromiseA) {
  65. res.then(resolve, reject);
  66. } else {
  67. resolve(res);
  68. }
  69. } catch (error) {
  70. reject(error);
  71. }
  72. });
  73. });
  74. }
  75. if (this.status === PromiseA.REJECTED) {
  76. return new PromiseA((resolve, reject) => {
  77. setTimeout(() => {
  78. try {
  79. let res = onRejected(this.value);
  80. if (res instanceof PromiseA) {
  81. res.then(resolve, reject);
  82. } else {
  83. reject(res);
  84. }
  85. } catch (error) {
  86. reject(error);
  87. }
  88. });
  89. });
  90. }
  91. }
  92. static resolve(value) {
  93. return new PromiseA((resolve, reject) => {
  94. if (value instanceof PromiseA) {
  95. value.then(resolve, reject);
  96. } else {
  97. resolve(value);
  98. }
  99. });
  100. }
  101. static reject(reason) {
  102. return new PromiseA((resolve, reject) => {
  103. if (reason instanceof PromiseA) {
  104. reason.then(resolve, reject);
  105. } else {
  106. reject(reason);
  107. }
  108. });
  109. }
  110. }

整了Promise源码真的很累,从看源码到整理思路,再到写完博客,花了我好几天,求求各位点一个赞吧👍!!