promise声明

首先呢,promise肯定是一个类,我们就用class来声明。
• 由于 new Promise((resolve, reject)=>{}) ,所以传入一个参数(函数),executor,传入就执行。
•executor里面有两个参数,一个叫resolve(成功),一个叫reject(失败)。
•由于resolve和reject可执行,所以都是函数
•Promise存在三个状态(state)pending、fulfilled、rejected

•pending(等待态)为初始态,并可以转化为fulfilled(成功态)和rejected(失败态)

•成功时,不可转为其他状态,且必须有一个不可改变的值(value)

•失败时,不可转为其他状态,且必须有一个不可改变的原因(reason)

• new Promise((resolve, reject)=>{resolve(value)}) resolve为成功,接收参数value,状态改变为fulfilled,不可再次改变。

• new Promise((resolve, reject)=>{reject(reason)}) reject为失败,接收参数reason,状态改变为rejected,不可再次改变。

•若是executor函数报错 直接执行reject();

  1. const PENDING = 'pending'; // 等待
  2. const FULFILLED = 'fulfilled'; // 成功
  3. const REJECTED = 'rejected'; // 失败
  4. class MyPromise {
  5. // 生成器
  6. constructor(executor) {
  7. // executor 立即执行
  8. // 成功执行 resolve或reject
  9. try {
  10. executor(this.resolve, this.reject);
  11. } catch (e) {
  12. //失败执行reject
  13. this.reject(e);
  14. }
  15. }
  16. status = PENDING;
  17. value = undefined;
  18. reason = undefined;
  19. resolve = (value) => {
  20. // 如果状态不是等待 阻止程序向下执行
  21. if (this.status !== PENDING) return;
  22. // 将状态更改为成功
  23. this.status = FULFILLED;
  24. // 保存成功之后的值
  25. this.value = value;
  26. };
  27. reject = (reason) => {
  28. // 如果状态不是等待 阻止程序向下执行
  29. if (this.status !== PENDING) return;
  30. // 将状态更改为失败
  31. this.status = REJECTED;
  32. // 保存失败后的原因
  33. this.reason = reason;
  34. }

then 方法

Promise有一个叫做then的方法,里面有两个参数:onFulfilled,onRejected,成功有成功的值,失败有失败的原因
•当状态state为fulfilled,则执行onFulfilled,传入this.value。当状态state为rejected,则执行onRejected,传入this.value
•onFulfilled,onRejected如果他们是函数,则必须分别在fulfilled,rejected后被调用,value或reason依次作为他们的第一个参数

  1. then(successCallback, failCallback) {
  2. // 同步情况下成功时执行成功回调
  3. if (this.status === FULFILLED) {
  4. successCallback(this.value);
  5. // 同步情况下失败时执行失败回调
  6. } else if (this.status === REJECTED) {
  7. failCallback(this.reason);
  8. }
  9. }

解决异步实现

现在基本可以实现简单的同步代码,但是当resolve在setTomeout内执行,then时state还是pending等待状态 我们就需要在then调用的时候,将成功和失败存到各自的数组,一旦reject或者resolve,就调用它们
类似于发布订阅,先将then里面的两个函数储存起来,由于一个promise可以有多个then,所以存在同一个数组内。

  1. const PENDING = 'pending'; // 等待
  2. const FULFILLED = 'fulfilled'; // 成功
  3. const REJECTED = 'rejected'; // 失败
  4. class MyPromise {
  5. // 生成器
  6. constructor(executor) {
  7. // executor 立即执行
  8. // 成功执行 resolve或reject
  9. try {
  10. executor(this.resolve, this.reject);
  11. } catch (e) {
  12. //失败执行reject
  13. this.reject(e);
  14. }
  15. }
  16. status = PENDING;
  17. value = undefined;
  18. reason = undefined;
  19. // 成功回调
  20. successCallback = [];
  21. // 失败回调
  22. failCallback = [];
  23. resolve = (value) => {
  24. // 如果状态不是等待 阻止程序向下执行
  25. if (this.status !== PENDING) return;
  26. // 将状态更改为成功
  27. this.status = FULFILLED;
  28. // 保存成功之后的值
  29. this.value = value;
  30. // 判断成功回调是否存在 如果存在 调用
  31. while (this.successCallback.length) {
  32. this.successCallback.shift()();
  33. }
  34. };
  35. reject = (reason) => {
  36. // 如果状态不是等待 阻止程序向下执行
  37. if (this.status !== PENDING) return;
  38. // 将状态更改为失败
  39. this.status = REJECTED;
  40. // 保存失败后的原因
  41. this.reason = reason;
  42. // 判断成功回调是否存在 如果存在 调用
  43. while (this.failCallback.length) {
  44. this.failCallback.shift()();
  45. }
  46. };
  47. then(successCallback, failCallback) {
  48. if (this.status === FULFILLED) {
  49. // 回调的函数是否异步
  50. successCallback(this.value);
  51. // 同步情况下失败时执行失败回调
  52. } else if (this.status === REJECTED) {
  53. failCallback(this.reason);
  54. //异步情况下执行
  55. } else {
  56. // onFulfilled传入到成功数组
  57. this.successCallback.push(() => {
  58. successCallback(this.value);
  59. });
  60. // onRejected传入到失败数组
  61. this.failCallback.push(() => {
  62. failCallback(this.reason);
  63. });
  64. }
  65. });
  66. }

解决链式调用

我门常常用到 new Promise().then().then() ,这就是链式调用,用来解决回调地狱

1、为了达成链式,我们默认在第一个then里返回一个promise。秘籍规定了一种方法,就是在then里面返回一个新的promise,称为promise2: promise2 = new Promise((resolve, reject)=>{})
•将这个promise2返回的值传递到下一个then中
•如果返回一个普通的值,则将普通的值传递给下一个then中

2、当我们在第一个then中 return 了一个参数(参数未知,需判断)。这个return出来的新的promise就是onFulfilled()或onRejected()的值

秘籍则规定onFulfilled()或onRejected()的值,即第一个then返回的值,叫做x,判断x的函数叫做resolvePromise

  1. const PENDING = 'pending'; // 等待
  2. const FULFILLED = 'fulfilled'; // 成功
  3. const REJECTED = 'rejected'; // 失败
  4. class MyPromise {
  5. // 生成器
  6. constructor(executor) {
  7. // executor 立即执行
  8. // 成功执行 resolve或reject
  9. try {
  10. executor(this.resolve, this.reject);
  11. } catch (e) {
  12. //失败执行reject
  13. this.reject(e);
  14. }
  15. }
  16. status = PENDING;
  17. value = undefined;
  18. reason = undefined;
  19. // 成功回调
  20. successCallback = [];
  21. // 失败回调
  22. failCallback = [];
  23. resolve = (value) => {
  24. // 如果状态不是等待 阻止程序向下执行
  25. if (this.status !== PENDING) return;
  26. // 将状态更改为成功
  27. this.status = FULFILLED;
  28. // 保存成功之后的值
  29. this.value = value;
  30. // 判断成功回调是否存在 如果存在 调用
  31. while (this.successCallback.length) {
  32. this.successCallback.shift()();
  33. }
  34. };
  35. reject = (reason) => {
  36. // 如果状态不是等待 阻止程序向下执行
  37. if (this.status !== PENDING) return;
  38. // 将状态更改为失败
  39. this.status = REJECTED;
  40. // 保存失败后的原因
  41. this.reason = reason;
  42. // 判断成功回调是否存在 如果存在 调用
  43. while (this.failCallback.length) {
  44. this.failCallback.shift()();
  45. }
  46. };
  47. then(successCallback, failCallback) {
  48. let promise2 = new MyPromise((resolve, reject) => {
  49. // 同步情况下成功时执行成功回调
  50. if (this.status === FULFILLED) {
  51. // 回调的函数是否异步
  52. try {
  53. let x = successCallback(this.value);
  54. resolvePromise(promise2, x, resolve, reject);
  55. } catch (e) {
  56. reject(e);
  57. }
  58. // 同步情况下失败时执行失败回调
  59. } else if (this.status === REJECTED) {
  60. try {
  61. let x = failCallback(this.reason);
  62. resolvePromise(promise2, x, resolve, reject);
  63. } catch (e) {
  64. reject(e);
  65. }
  66. //异步情况下执行
  67. } else {
  68. // onFulfilled传入到成功数组
  69. this.successCallback.push(() => {
  70. try {
  71. let x = successCallback(this.value);
  72. resolvePromise(promise2, x, resolve, reject);
  73. } catch (e) {
  74. reject(e);
  75. }
  76. });
  77. // onRejected传入到失败数组
  78. this.failCallback.push(() => {
  79. try {
  80. let x = successCallback(this.value);
  81. resolvePromise(promise2, x, resolve, reject);
  82. } catch (e) {
  83. reject(e);
  84. }
  85. });
  86. }
  87. });
  88. return promise2;
  89. }
  90. }

完成resolvePromise函数

秘籍规定了一段代码,让不同的promise代码互相套用,叫做resolvePromise
•如果 x === promise2,则是会造成循环引用,自己等待自己完成,则报“循环引用”错误

  1. let p = new Promise(resolve => {
  2. resolve(0);
  3. });
  4. var p2 = p.then(data => {
  5. // 循环引用,自己等待自己完成,一辈子完不成
  6. return p2;
  7. })

1、判断x
• Otherwise, if x is an object or function,Let then be x.then
•x 不能是null
•x 是普通值 直接resolve(x)
• x 是对象或者函数(包括promise), let then = x.then 2、当x是对象或者函数(默认promise)
•声明了then
•如果取then报错,则走reject()
•如果then是个函数,则用call执行then,第一个参数是this,后面是成功的回调和失败的回调
•如果成功的回调还是pormise,就递归继续解析 3、成功和失败只能调用一个 所以设定一个called来防止多次调用

  1. function resolvePromise(promsie2, x, resolve, reject) {
  2. if (promsie2 === x) {
  3. return reject(new TypeError('Chaining cycle detected for promis'));
  4. }
  5. if (x instanceof MyPromise) {
  6. // promise 对象
  7. x.then(
  8. (value) => resolve(value),
  9. (reason) => reject(reason)
  10. );
  11. } else {
  12. // 普通值
  13. resolve(x);
  14. }
  15. }

解决其他问题

1、秘籍规定onFulfilled,onRejected都是可选参数,如果他们不是函数,必须被忽略
• onFulfilled返回一个普通的值,成功时直接等于 value => value
• onRejected返回一个普通的值,失败时如果直接等于 value => value,则会跑到下一个then中的onFulfilled中,所以直接扔出一个错误 reason => throw err 2、秘籍规定onFulfilled或onRejected不能同步被调用,必须异步调用。我们就用setTimeout解决异步问题
•如果onFulfilled或onRejected报错,则直接返回reject()

  1. const PENDING = 'pending'; // 等待
  2. const FULFILLED = 'fulfilled'; // 成功
  3. const REJECTED = 'rejected'; // 失败
  4. class MyPromise {
  5. // 生成器
  6. constructor(executor) {
  7. // executor 立即执行
  8. // 成功执行 resolve或reject
  9. try {
  10. executor(this.resolve, this.reject);
  11. } catch (e) {
  12. //失败执行reject
  13. this.reject(e);
  14. }
  15. }
  16. status = PENDING;
  17. value = undefined;
  18. reason = undefined;
  19. // 成功回调
  20. successCallback = [];
  21. // 失败回调
  22. failCallback = [];
  23. resolve = (value) => {
  24. // 如果状态不是等待 阻止程序向下执行
  25. if (this.status !== PENDING) return;
  26. // 将状态更改为成功
  27. this.status = FULFILLED;
  28. // 保存成功之后的值
  29. this.value = value;
  30. // 判断成功回调是否存在 如果存在 调用
  31. while (this.successCallback.length) {
  32. this.successCallback.shift()();
  33. }
  34. };
  35. reject = (reason) => {
  36. // 如果状态不是等待 阻止程序向下执行
  37. if (this.status !== PENDING) return;
  38. // 将状态更改为失败
  39. this.status = REJECTED;
  40. // 保存失败后的原因
  41. this.reason = reason;
  42. // 判断成功回调是否存在 如果存在 调用
  43. while (this.failCallback.length) {
  44. this.failCallback.shift()();
  45. }
  46. };
  47. then(successCallback, failCallback) {
  48. // successCallback如果不是函数,就忽略successCallback,直接返回value
  49. successCallback = successCallback ? successCallback : (value) => value;
  50. // failCallback如果不是函数,就忽略failCallback,直接扔出错误
  51. failCallback = failCallback
  52. ? failCallback
  53. : (reason) => {
  54. throw reason;
  55. };
  56. let promise2 = new MyPromise((resolve, reject) => {
  57. // 同步情况下成功时执行成功回调
  58. if (this.status === FULFILLED) {
  59. // 回调的函数是否异步
  60. setTimeout(() => {
  61. try {
  62. let x = successCallback(this.value);
  63. resolvePromise(promise2, x, resolve, reject);
  64. } catch (e) {
  65. reject(e);
  66. }
  67. }, 0);
  68. // 同步情况下失败时执行失败回调
  69. } else if (this.status === REJECTED) {
  70. setTimeout(() => {
  71. try {
  72. let x = failCallback(this.reason);
  73. resolvePromise(promise2, x, resolve, reject);
  74. } catch (e) {
  75. reject(e);
  76. }
  77. }, 0);
  78. //异步情况下执行
  79. } else {
  80. // onFulfilled传入到成功数组
  81. this.successCallback.push(() => {
  82. setTimeout(() => {
  83. try {
  84. let x = successCallback(this.value);
  85. resolvePromise(promise2, x, resolve, reject);
  86. } catch (e) {
  87. reject(e);
  88. }
  89. }, 0);
  90. });
  91. // onRejected传入到失败数组
  92. this.failCallback.push(() => {
  93. setTimeout(() => {
  94. try {
  95. let x = successCallback(this.value);
  96. resolvePromise(promise2, x, resolve, reject);
  97. } catch (e) {
  98. reject(e);
  99. }
  100. }, 0);
  101. });
  102. }
  103. });
  104. return promise2;
  105. }
  106. }
  107. function resolvePromise(promsie2, x, resolve, reject) {
  108. if (promsie2 === x) {
  109. return reject(new TypeError('Chaining cycle detected for promis'));
  110. }
  111. if (x instanceof MyPromise) {
  112. // promise 对象
  113. x.then(
  114. (value) => resolve(value),
  115. (reason) => reject(reason)
  116. );
  117. } else {
  118. // 普通值
  119. resolve(x);
  120. }
  121. }

catch

  1. catch(fn){
  2. return this.then(null,fn);
  3. }

resolve

  1. //resolve方法
  2. static resolve = (val) => {
  3. return new Promise((resolve, reject) => {
  4. resolve(val);
  5. });
  6. };

reject

  1. //reject方法
  2. static reject = (val) => {
  3. return new Promise((resolve, reject) => {
  4. reject(val);
  5. });
  6. };

race

  1. //race方法
  2. static race = (promises) => {
  3. return new Promise((resolve, reject) => {
  4. for (let i = 0; i < promises.length; i++) {
  5. promises[i].then(resolve, reject);
  6. }
  7. });
  8. };

all

  1. static all = (promises)=>{
  2. let arr = [];
  3. let i = 0;
  4. function processData(index,data){
  5. arr[index] = data;
  6. i++;
  7. if(i == promises.length){
  8. resolve(arr);
  9. };
  10. };
  11. return new Promise((resolve,reject)=>{
  12. for(let i=0;i<promises.length;i++){
  13. promises[i].then(data=>{
  14. processData(i,data);
  15. },reject);
  16. };
  17. });
  18. }

完整代码

  1. const PENDING = 'pending'; // 等待
  2. const FULFILLED = 'fulfilled'; // 成功
  3. const REJECTED = 'rejected'; // 失败
  4. class MyPromise {
  5. // 生成器
  6. constructor(executor) {
  7. // executor 立即执行
  8. // 成功执行 resolve或reject
  9. try {
  10. executor(this.resolve, this.reject);
  11. } catch (e) {
  12. //失败执行reject
  13. this.reject(e);
  14. }
  15. }
  16. status = PENDING;
  17. value = undefined;
  18. reason = undefined;
  19. // 成功回调
  20. successCallback = [];
  21. // 失败回调
  22. failCallback = [];
  23. resolve = (value) => {
  24. // 如果状态不是等待 阻止程序向下执行
  25. if (this.status !== PENDING) return;
  26. // 将状态更改为成功
  27. this.status = FULFILLED;
  28. // 保存成功之后的值
  29. this.value = value;
  30. // 判断成功回调是否存在 如果存在 调用
  31. while (this.successCallback.length) {
  32. this.successCallback.shift()();
  33. }
  34. };
  35. reject = (reason) => {
  36. // 如果状态不是等待 阻止程序向下执行
  37. if (this.status !== PENDING) return;
  38. // 将状态更改为失败
  39. this.status = REJECTED;
  40. // 保存失败后的原因
  41. this.reason = reason;
  42. // 判断成功回调是否存在 如果存在 调用
  43. while (this.failCallback.length) {
  44. this.failCallback.shift()();
  45. }
  46. };
  47. then(successCallback, failCallback) {
  48. // successCallback如果不是函数,就忽略successCallback,直接返回value
  49. successCallback = successCallback ? successCallback : (value) => value;
  50. // failCallback如果不是函数,就忽略failCallback,直接扔出错误
  51. failCallback = failCallback
  52. ? failCallback
  53. : (reason) => {
  54. throw reason;
  55. };
  56. let promise2 = new MyPromise((resolve, reject) => {
  57. // 同步情况下成功时执行成功回调
  58. if (this.status === FULFILLED) {
  59. // 回调的函数是否异步
  60. setTimeout(() => {
  61. try {
  62. let x = successCallback(this.value);
  63. resolvePromise(promise2, x, resolve, reject);
  64. } catch (e) {
  65. reject(e);
  66. }
  67. }, 0);
  68. // 同步情况下失败时执行失败回调
  69. } else if (this.status === REJECTED) {
  70. setTimeout(() => {
  71. try {
  72. let x = failCallback(this.reason);
  73. resolvePromise(promise2, x, resolve, reject);
  74. } catch (e) {
  75. reject(e);
  76. }
  77. }, 0);
  78. //异步情况下执行
  79. } else {
  80. // onFulfilled传入到成功数组
  81. this.successCallback.push(() => {
  82. setTimeout(() => {
  83. try {
  84. let x = successCallback(this.value);
  85. resolvePromise(promise2, x, resolve, reject);
  86. } catch (e) {
  87. reject(e);
  88. }
  89. }, 0);
  90. });
  91. // onRejected传入到失败数组
  92. this.failCallback.push(() => {
  93. setTimeout(() => {
  94. try {
  95. let x = successCallback(this.value);
  96. resolvePromise(promise2, x, resolve, reject);
  97. } catch (e) {
  98. reject(e);
  99. }
  100. }, 0);
  101. });
  102. }
  103. });
  104. return promise2;
  105. }
  106. catch(fn) {
  107. return this.then(null, fn);
  108. }
  109. //resolve方法
  110. static resolve = (val) => {
  111. return new Promise((resolve, reject) => {
  112. resolve(val);
  113. });
  114. };
  115. //reject方法
  116. static reject = (val) => {
  117. return new Promise((resolve, reject) => {
  118. reject(val);
  119. });
  120. };
  121. //race方法
  122. static race = (promises) => {
  123. return new Promise((resolve, reject) => {
  124. for (let i = 0; i < promises.length; i++) {
  125. promises[i].then(resolve, reject);
  126. }
  127. });
  128. };
  129. static all = (promises)=>{
  130. let arr = [];
  131. let i = 0;
  132. function processData(index,data){
  133. arr[index] = data;
  134. i++;
  135. if(i == promises.length){
  136. resolve(arr);
  137. };
  138. };
  139. return new Promise((resolve,reject)=>{
  140. for(let i=0;i<promises.length;i++){
  141. promises[i].then(data=>{
  142. processData(i,data);
  143. },reject);
  144. };
  145. });
  146. }
  147. }
  148. function resolvePromise(promsie2, x, resolve, reject) {
  149. if (promsie2 === x) {
  150. return reject(new TypeError('Chaining cycle detected for promis'));
  151. }
  152. if (x instanceof MyPromise) {
  153. // promise 对象
  154. x.then(
  155. (value) => resolve(value),
  156. (reason) => reject(reason)
  157. );
  158. } else {
  159. // 普通值
  160. resolve(x);
  161. }
  162. }

参考链接

[转]史上最最最详细的手写Promise教程