阅读 184

Promise从入门开始手写(promise什么意思)

Promise认知

promise用于异步变成的一种方式,表示一种期约/约定。有自己的状态且状态唯一,一旦改变就不可在变。 可以用来解决回调地狱的问题,也可以结合async await来实现异步代码同步化操作。

基本使用

const promise = new Promise((resolve,reject)=>{     resolve("成功");     //reject("失败"); }) 复制代码

promise拥有自己的状态,代表一种约定,一旦状态改变这个约定就有了结果,即状态不能再次被改变。

关于状态的改变:需要使用resolve方法来改变promise状态为成功的状态,使用reject方法来改变promise状态为失败的状态。

Promise类接收一个函数参数,可以称它为执行器,他在创建Promise对象的时候就会被调用。

    /*     1.定义一个MyPromise类     2.该类有自己的状态 分别为初始化时,成功,失败,状态是固定的,可以使用定义常量的方式来定义。     2.该类接收一个立即执行的执行器函数     3.改执行器函数接收两个参数resolve与reject,这两个函数不是我们创建的,是promise自带的,所以我们要在promise里定义这两个函数     4.调用resolve方法会改吧promise状态为成功,且promise状态只能在pending时被改变,且只能改变一次,所以要判断状态为pending时才改变状态     */     //定义状态常量     const PENDING = 'pening'//初始化状态     const FULFILLED = 'fulfilled'//成功的状态     const REJECTED = 'rejected'//失败的状态     class MyPromise{         //创建时初始化状态为pending         status = PENDING;         constructor(executor){             executor(this.resolve,this.reject)         }         //之所以写成箭头函数是因为this的指向。不清楚的可以运行一下下面的例子         resolve = ()=>{             //判断状态为初始状态才改变状态值             if(this.status === PENDING){                 this.status = FULFILLED             }         }         reject = ()=>{             if(this.status === PENDING){                 this.status = REJECTED             }         }     }     const promise1 = new MyPromise((resolve,reject)=>{         resolve()     })     console.log(promise1) 复制代码

用箭头函数与不用箭头函数的比较,resolve用箭头函数写,reject用普通函数写,比较两者

    const PENDING = 'pening'//初始化状态     const FULFILLED = 'fulfilled'//成功的状态     const REJECTED = 'rejected'//失败的状态     class MyPromise{         //创建时初始化状态为pending         status = PENDING;         constructor(executor){             executor(this.resolve,this.reject)         }         //之所以写成箭头函数是因为this的指向。不清楚的可以运行一下下面的例子         resolve = ()=>{             //判断状态为初始状态才改变状态值             if(this.status === PENDING){                 this.status = FULFILLED             }         }         reject = function{             if(this.status === PENDING){                 this.status = REJECTED             }         }     }     const promise1 = new MyPromise((resolve,reject)=>{         resolve()     })     console.log("箭头函数",promise1)     const promise2 = new MyPromise((resolve,reject)=>{         reject()     })     console.log("普通函数",promise1) 复制代码

得到如下结果,正常打印箭头函数,普通函数会报错。因为是this的指向问题。箭头函数没有自身的this,它的this是他上层函数的this,且在创建时已经确定,如果是普通函数,他是this在调用的时候确定,而我们使用resolve和reject的时候是直接调用的他的this为undefined,所以会报错。

image.png

创建的promise对象的状态改变之后就会触发相应的then方法。

const promise = new Promise((resolve,reject)=>{     resolve("成功");     //reject("失败"); }) promise.then(value=>{     console.log("成功的状态:",value) },reason=>{     console.log("失败的原因:",reason) }) 复制代码

promise对象状态改变之后触发相应的then方法,也就是promise实例有then方法。这个方法接受两个外部传入的函数,来处理相应的成功/失败的逻辑。

    const PENDING = 'pening'     const FULFILLED = 'fulfilled'     const REJECTED = 'rejected'     class MyPromise{         status = PENDING;         //初始化value与reason         value = undefined;         reason = undefined;         constructor(executor){             executor(this.resolve,this.reject)         }         resolve = (value)=>{             if(this.status === PENDING){                 this.status = FULFILLED;                 //成功则改变value为传入的值                 this.value = value;                              }         }         reject = (reason)=>{             if(this.status === PENDING){                 //失败则改变reason 为传入的值                 this.status = REJECTED;                 this.reason =reason;             }         }         //为primose实例新增then方法,接受两个函数参数/分布来处理相应的成功/失败的逻辑。         //必须在相应的状态执行相应的逻辑         //成功的状态调用传入的第一个函数参数,此函数参数的参数为修改状态为成功时调用的resolve方法传入的参数this.value         //失败的状态调用传入的第二个函数参数,此函数参数的参数为修改状态为失败时调用的reject方法传入的参数this.reason         then = (fulfilled,rejected)=>{             if(this.status === FULFILLED){                 fulfilled(this.value)             }             else if(this.status === REJECTED){                 rejected(this.reason)             }         }     }     const promise1 = new MyPromise((resolve,reject)=>{         resolve()     })     promise1.then(value=>{         console.log("成功状态:",value)     },reason=>{         console.log("失败状态:",reason)     })      复制代码

异步逻辑

JS代码的运行分为同步任务与异步任务。上面定义的myPromise运行同步代码是没有问题的,当创建一个新的promise对象时,直接改变了他的状态,在接下来使用此promise的then方法,此处状态已经改变,所以会按照他的状态执行接下来的流程。但是如果创建promise时改变promise状态的操作是异步的,如使用定时器在几秒之后再改变promise的状态,此时执行到then方法时,状态还是pending状态,而上面定义的myPromise并没有在状态为pending时的处理逻辑。所以我们应该为状态为pending时添加相应的处理逻辑。看下面的代码。

//沿用上面定义的MyPromise const promise = new MyPromise((resolve,reject)=>{     setTimeout(()=>{         resolve("延迟2s改变状态")     },2000) }) promise.then(value=>{     console.log(value) },reason=>{     console.log(reason) }) /*    创建了一个promise对象。执行器中有setTimeout会把定时器中的逻辑加入异步队列。    继续执行promise对象的then方法,此时promise的状态为pending不会进行任何操作。    同步代码执行完毕,检查异步对列,发现有一个,则在时间到达时执行异步逻辑,设置promise的状态为成功的状态。所以上面的代码不会有任何输出。        经过上面的分析,问题出在执行then方法时,promise的状态还没有改变,所以不会进行任何操作。我们要做的就是,如果在执行then方法时promise的状态为pending,则把相应的逻辑存储起来,等到状态改变时执行相应的逻辑。     */ 复制代码

修改MyPromise代码如下

    const PENDING = 'pening'     const FULFILLED = 'fulfilled'     const REJECTED = 'rejected'     class MyPromise{         status = PENDING;         value = undefined;         reason = undefined;         //初始化then传入的成功时缓存的相关逻辑         fulfilledCallback = undefined;         //初始化then传入的失败时缓存的相关逻辑         rejectedCallback = undefined;         constructor(executor){             executor(this.resolve,this.reject)         }         resolve = (value)=>{             if(this.status === PENDING){                 this.status = FULFILLED;                 this.value = value;                 //状态改变为成功时时,如果有缓存的成功状态的相关逻辑,则执行                 this.fulfilledCallback && this.fulfilledCallback(this.value)             }         }         reject = (reason)=>{             if(this.status === PENDING){                 this.status = REJECTED;                 this.reason =reason;                 //状态改变为失败时,如果有缓存的失败状态的相关逻辑,则执行                 this.rejectedCallback && this.rejectedCallback(this.reason)             }         }         then = (fulfilled,rejected)=>{             if(this.status === FULFILLED){                 fulfilled(this.value)             }             else if(this.status === REJECTED){                 rejected(this.reason)             }             //如果状态为pending则存储then传入的执行逻辑             else{                 this.fulfilledCallback = fulfilled;                 this.rejectedCallback =rejected;             }         }     }     const promise1 = new MyPromise((resolve,reject)=>{         setTimeout(()=>{             resolve("延迟2秒改变状态为成功")         },2000)     })     promise1.then(value=>{         console.log("成功状态:",value)     },reason=>{         console.log("失败状态:",reason)     }) 复制代码

多次调用then方法

同一个promise对象是可以多次调用then方法的,不管调用多少次then方法,在状态已经改变的请求下。都会按照状态来执行相关逻辑。但是如果是异步逻辑,多次调用then方法时,promise状态还没有改变,按照我们上面的代码,直接对fulfilledCallback或者是rejectedCallback进行赋值的话,就只会执行最后一次的逻辑。而每一次then方法的逻辑都应该在状态改变之后执行,也就是说需要存储多个函数,并且在状态改变之后执行。改写myPromise代码如下。

    const PENDING = 'pening'     const FULFILLED = 'fulfilled'     const REJECTED = 'rejected'     class MyPromise{         status = PENDING;         value = undefined;         reason = undefined;         //可能会有多个逻辑,所以改写为数组类型         fulfilledCallback = [];         rejectedCallback = [];         constructor(executor){             executor(this.resolve,this.reject)         }         resolve = (value)=>{             if(this.status === PENDING){                 this.status = FULFILLED;                 this.value = value;                 //执行成功状态数组中的每一个函数,执行顺序为第一个先执行。                 while(this.fulfilledCallback.length){                     //用shift方法从最前面开始取函数执行                     this.fulfilledCallback.shift()(this.value)                 }             }         }         reject = (reason)=>{             if(this.status === PENDING){                 this.status = REJECTED;                 this.reason =reason;                  //执行失败状态数组中的每一个函数,执行顺序为第一个先执行。                 while(this.rejectedCallback.length){                     //用shift方法从最前面开始取函数执行                     this.rejectedCallback.shift()(this.reason)                 }             }         }         then = (fulfilled,rejected)=>{             if(this.status === FULFILLED){                 fulfilled(this.value)             }             else if(this.status === REJECTED){                 rejected(this.reason)             }             //如果状态为pending则给相关数组加入相关函数             else{                 this.fulfilledCallback.push(fulfilled);                 this.rejectedCallback.push(rejected);             }         }     }     const promise1 = new MyPromise((resolve,reject)=>{         setTimeout(()=>{             resolve("延迟2秒改变状态为成功")         },2000)     })     promise1.then(value=>{         console.log("成功状态1:",value)     },reason=>{         console.log("失败状态1:",reason)     })     promise1.then(value=>{         console.log("成功状态2:",value)     },reason=>{         console.log("失败状态2:",reason)     })     promise1.then(value=>{         console.log("成功状态3:",value)     },reason=>{         console.log("失败状态3:",reason)     }) 复制代码

then方法的链式调用

then方法可以链式调用,链式调用的基本使用

const promise = new Promise((resolve,reject)=>{     resolve("第一次链式调用") }) promise.then(value=>{     console.log(value)     return "第二次链式调用" }).then(value=>{     console.log(value) }) //打印第一次链式调用 //第二次链式调用 复制代码

从上面代码可以看出,then可以进行链式调用,那么then应该返回一个promise对象。且该promise对象的then方法传入的成功的回调与失败的回调的参数是上一个then方法的返回值。

    const PENDING = 'pening'     const FULFILLED = 'fulfilled'     const REJECTED = 'rejected'     class MyPromise{         status = PENDING;         value = undefined;         reason = undefined;         fulfilledCallback = [];         rejectedCallback = [];         constructor(executor){             executor(this.resolve,this.reject)         }         resolve = (value)=>{             if(this.status === PENDING){                 this.status = FULFILLED;                 this.value = value;                 while(this.fulfilledCallback.length){                     this.fulfilledCallback.shift()(this.value)                 }             }         }         reject = (reason)=>{             if(this.status === PENDING){                 this.status = REJECTED;                 this.reason =reason;                 while(this.rejectedCallback.length){                     this.rejectedCallback.shift()(this.reason)                 }             }         }         then = (fulfilled,rejected)=>{             //then方法需要返回一个promise对象             const promise2 = new MyPromise((resolve,reject)=>{                  if(this.status === FULFILLED){                      //接受返回值,作为下一次then的参数                     const x = fulfilled(this.value)                     resolve(x)                 }                 else if(this.status === REJECTED){                     rejected(this.reason)                 }                 else{                     this.fulfilledCallback.push(fulfilled);                     this.rejectedCallback.push(rejected);                 }             })                         return promise2         }     }     const promise1 = new MyPromise((resolve,reject)=>{         resolve("第一次链式调用")     })     promise1.then(value=>{         console.log(value)         return "第二次链式调用"     }).then(value=>{         console.log(value)     }) 复制代码

then方法不止可以返回普通的数据,还可能返回promise对象,更加返回类型不同需要做不同的处理,如果返回的是一个普通的值,则直接调用resolve方法,传递返回值即可。如果是promise对象则要根据promise对象的状态来确定是调用resolve还是reject方法。

    const PENDING = 'pening'     const FULFILLED = 'fulfilled'     const REJECTED = 'rejected'     class MyPromise{         status = PENDING;         value = undefined;         reason = undefined;         fulfilledCallback = [];         rejectedCallback = [];         constructor(executor){             executor(this.resolve,this.reject)         }         resolve = (value)=>{             if(this.status === PENDING){                 this.status = FULFILLED;                 this.value = value;                 while(this.fulfilledCallback.length){                     this.fulfilledCallback.shift()(this.value)                 }             }         }         reject = (reason)=>{             if(this.status === PENDING){                 this.status = REJECTED;                 this.reason =reason;                 while(this.rejectedCallback.length){                     this.rejectedCallback.shift()(this.reason)                 }             }         }         then = (fulfilled,rejected)=>{             //then方法需要返回一个promise对象             const promise2 = new MyPromise((resolve,reject)=>{                  if(this.status === FULFILLED){                      //接受返回值,作为下一次then的参数                     const x = fulfilled(this.value)                     //判断返回值类型做不同的处理,多个地方要使用,所以封装成一个函数                     resolvePromise(x,resolve,reject)                 }                 else if(this.status === REJECTED){                     rejected(this.reason)                 }                 else{                     this.fulfilledCallback.push(fulfilled);                     this.rejectedCallback.push(rejected);                 }             })                         return promise2         }     }     function resolvePromise(x,resolve,reject){         //判断x的值,如果是普通值则直接resolve,promise类型的值则根据promise状态确定调用哪个方法         if(x instanceof MyPromise){             x.then(value=>resolve(value),reason=>reject(reason))         }         else{             resolve(x)         }     }     const promise1 = new MyPromise((resolve,reject)=>{         resolve("第一次链式调用")     })     promise1.then(value=>{         console.log(value)         return new MyPromise((resolve,reject)=>{             resolve("返回一个promsie对象")         })     }).then(value=>{         console.log(value)     }) 复制代码

then方法返回的promise对象不能是他执行完毕之后返回的promise对象,否则会发生循环引用。

  const promise = new Promise((resolve,reject)=>{         resolve("第一次调用")     })   const promise1 = promise.then(value=>{         console.log(value)         return promise1     })     //第一次调用     // UnhandledPromiseRejectionWarning: TypeError: Chaining cycle detected for promise #<Promise> 复制代码

像上面这样就会出现循环引用报错。改写MyPromise

    const PENDING = 'pening'     const FULFILLED = 'fulfilled'     const REJECTED = 'rejected'     class MyPromise{         status = PENDING;         value = undefined;         reason = undefined;         fulfilledCallback = [];         rejectedCallback = [];         constructor(executor){             executor(this.resolve,this.reject)         }         resolve = (value)=>{             if(this.status === PENDING){                 this.status = FULFILLED;                 this.value = value;                 while(this.fulfilledCallback.length){                     this.fulfilledCallback.shift()(this.value)                 }             }         }         reject = (reason)=>{             if(this.status === PENDING){                 this.status = REJECTED;                 this.reason =reason;                 while(this.rejectedCallback.length){                     this.rejectedCallback.shift()(this.reason)                 }             }         }         then = (fulfilled,rejected)=>{             const promise2 = new MyPromise((resolve,reject)=>{                  if(this.status === FULFILLED){                     //需要判断promise2与x是不是同一个对象,同一对象则会循环引用                     //promise2会在函数执行完毕之后才会创建,要想在这里使用,需要使用异步任务                     setTimeout(()=>{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,reslove,reject)                     },0)                 }                 else if(this.status === REJECTED){                     rejected(this.reason)                 }                 else{                     this.fulfilledCallback.push(fulfilled);                     this.rejectedCallback.push(rejected);                 }             })                         return promise2         }     }     function resolvePromise(promise2,x,resolve,reject){         //相同则reject给一个类型错误信息         if(promise2 === x){            return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))         }         if(x instanceof MyPromise){             x.then(value=>resolve(value),reason=>reject(reason))         }         else{             resolve(x)         }     } const promise1 = new MyPromise((resolve,reject)=>{     resolve("第一次链式调用") }) const promise2 = promise1.then(value=>{     console.log(value)     return promise2 }) promise2.then(value=>{},reason=>{     console.log(reason) }) 复制代码

错误处理及失败状态代码补全

在代码执行过程中,是可能会发生错误的,当错误出现的时候我们要捕获这个错误,并且把promise的状态设置为reject。

可能发生错误的地方有执行器执行的时候,then方法调用的时候。

    const PENDING = 'pening'     const FULFILLED = 'fulfilled'     const REJECTED = 'rejected'     class MyPromise{         status = PENDING;         value = undefined;         reason = undefined;         fulfilledCallback = [];         rejectedCallback = [];         constructor(executor){             //如果执行器出现错误,则改变状态为reject             try{                 executor(this.resolve,this.reject)             }             catch(err){                 this.reject(err)             }                      }         resolve = (value)=>{             if(this.status === PENDING){                 this.status = FULFILLED;                 this.value = value;                 while(this.fulfilledCallback.length){                     //下面改写之后传递了参数,这里不用再传                     this.fulfilledCallback.shift()()                 }             }         }         reject = (reason)=>{             if(this.status === PENDING){                 this.status = REJECTED;                 this.reason =reason;                 while(this.rejectedCallback.length){                     //下面改写之后传递了参数,这里不用再传                     this.rejectedCallback.shift()()                 }             }         }         then = (fulfilled,rejected)=>{             const promise2 = new MyPromise((resolve,reject)=>{                  if(this.status === FULFILLED){                     //需要判断promise2与x是不是同一个对象,同一对象则会循环引用                     //promise2会在函数执行完毕之后才会创建,要想在这里使用,需要使用异步任务                     setTimeout(()=>{                         //执行fulfilled时出现错误也要吧状态改为reject,给后面的then使用                         try{                             const x = fulfilled(this.value)                             resolvePromise(promise2,x,resolve,reject)                         }                         catch(err){                             reject(err)                         }                      },0)                 }                 else if(this.status === REJECTED){                     //参照成功状态补全失败状态代码                     //需要判断promise2与x是不是同一个对象,同一对象则会循环引用                     //promise2会在函数执行完毕之后才会创建,要想在这里使用,需要使用异步任务                     setTimeout(()=>{                         //执行fulfilled时出现错误也要吧状态改为reject,给后面的then使用                         try{                             const x = rejected(this.reason)                             resolvePromise(promise2,x,resolve,reject)                         }                         catch(err){                             reject(err)                         }                      },0)                 }                 else{                     //参照成功状态进行改下存储的函数                     this.fulfilledCallback.push(()=>{                           setTimeout(()=>{                         //执行fulfilled时出现错误也要吧状态改为reject,给后面的then使用                         try{                             const x = fulfilled(this.value)                             resolvePromise(promise2,x,resolve,reject)                         }                         catch(err){                             reject(err)                         }                      },0)                     })                     this.rejectedCallback.push(()=>{                          setTimeout(()=>{                         //执行fulfilled时出现错误也要吧状态改为reject,给后面的then使用                         try{                             const x = rejected(this.reason)                             resolvePromise(promise2,x,resolve,reject)                         }                         catch(err){                             reject(err)                         }                      },0)                     });                 }             })                         return promise2         }     }     function resolvePromise(promise2,x,resolve,reject){         if(promise2 === x){            return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))         }         if(x instanceof MyPromise){             x.then(value=>resolve(value),reason=>reject(reason))         }         else{             resolve(x)         }     } const promise1 = new MyPromise((resolve,reject)=>{  setTimeout(() => {      resolve("成功")  }, 2000); }) promise1.then(value=>{     console.log(value)     return "返回一个普通值" }).then(value=>{     console.log(value) }) 复制代码

将then方法参数变为可选参数

promise中如果then方法没有传参,那么他的状态是可以原样向后传递的,如

const promise = new Promise(resolve,reject=>{     reject("成功") }) promise.then().then().then(value=>{     console.log(value) }) //最后会打印成功 //等同于下面的代码 promise.then(value=>value).then(value=>value).then(value=>{     console.log(value) }) 复制代码

判断then方法参数是否存在

    const PENDING = 'pening'     const FULFILLED = 'fulfilled'     const REJECTED = 'rejected'     class MyPromise{         status = PENDING;         value = undefined;         reason = undefined;         fulfilledCallback = [];         rejectedCallback = [];         constructor(executor){             //如果执行器出现错误,则改变状态为reject             try{                 executor(this.resolve,this.reject)             }             catch(err){                 this.reject(err)             }                      }         resolve = (value)=>{             if(this.status === PENDING){                 this.status = FULFILLED;                 this.value = value;                 while(this.fulfilledCallback.length){                     //下面改写之后传递了参数,这里不用再传                     this.fulfilledCallback.shift()()                 }             }         }         reject = (reason)=>{             if(this.status === PENDING){                 this.status = REJECTED;                 this.reason =reason;                 while(this.rejectedCallback.length){                     //下面改写之后传递了参数,这里不用再传                     this.rejectedCallback.shift()()                 }             }         }         then = (fulfilled,rejected)=>{             //需要判断fulfilled与rejected是否存在,存在则进行之前的逻辑,不存在的话给他一个默认函数             fulfilled = fulfilled ? fulfilled :value=>value;             //用throw才能改变状态为失败。用来传递错误             rejected = rejected ? rejected :reason=>{throw reason};             const promise2 = new MyPromise((resolve,reject)=>{                  if(this.status === FULFILLED){                     setTimeout(()=>{                         try{                             const x = fulfilled(this.value)                             resolvePromise(promise2,x,resolve,reject)                         }                         catch(err){                             reject(err)                         }                      },0)                 }                 else if(this.status === REJECTED){                     setTimeout(()=>{                         try{                             const x = rejected(this.reason)                             resolvePromise(promise2,x,resolve,reject)                         }                         catch(err){                             reject(err)                         }                      },0)                 }                 else{                     this.fulfilledCallback.push(()=>{                           setTimeout(()=>{                         try{                             const x = fulfilled(this.value)                             resolvePromise(promise2,x,resolve,reject)                         }                         catch(err){                             reject(err)                         }                      },0)                     })                     this.rejectedCallback.push(()=>{                          setTimeout(()=>{                         try{                             const x = rejected(this.reason)                             resolvePromise(promise2,x,resolve,reject)                         }                         catch(err){                             reject(err)                         }                      },0)                     });                 }             })                         return promise2         }     }     function resolvePromise(promise2,x,resolve,reject){         if(promise2 === x){            return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))         }         if(x instanceof MyPromise){             x.then(value=>resolve(value),reason=>reject(reason))         }         else{             resolve(x)         }     } const promise1 = new MyPromise((resolve,reject)=>{  resolve("成功") }) promise1.then().then().then(value=>{     console.log(value) }) 复制代码

Promise.all

Promise.all可以同时执行多个promise,返回一个promise对象,只有当所有的promise的状态为成功的状态,他的状态才为成功,接受到的成功的数据为一个数组,结果数组顺序和传入promise的顺序一致,有一个失败则为失败的状态,且失败的原因为失败的promise的原因。

const PENDING = 'pening' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise{     status = PENDING;     value = undefined;     reason = undefined;     fulfilledCallback = [];     rejectedCallback = [];     //all通过类名直接调用,所以他是一个静态方法,接受一个数组,数组元素可以使普通数据也可以是promise对象     static all(arr){         //定义一个结果数组来存储获得数据         return new MyPromise((resolve,reject)=>{             let result = [];             //如果遇到异步任务,forEach会先执行完毕,如果直接resolve的话,会造成异步任务结果为空,只有等待所有promise都拿到了结果且放进result数组之后才能进行resolve。定义一个变量来检查是否全部添加完成。             let resultIndex = 0;             //遍历拿到所有的数组元素             arr.forEach((item,index)=>{             //如果是普通数据,则直接得到这个数据,如果是promise对象则要根据对象状态来确定操作                 if(item instanceof MyPromise){                     //成功状态把成功的值给结果数组,失败则状态改变为失败,传递失败的原因                     item.then(value=>{                         result[index] = value;                         resultIndex++;                         //已添加的数量等于传入的数量时才改变状态                         if(resultIndex === arr.length){                             resolve(result)                         }                       },reason=>reject(reason))                 }                 else{                     result[index] = item;                     resultIndex++;                     //已添加的数量等于传入的数量时才改变状态                     if(resultIndex === arr.length){                         resolve(result)                     }                   }                             })         })            }     constructor(executor){         try{             executor(this.resolve,this.reject)         }         catch(err){             this.reject(err)         }     }     resolve = (value)=>{         if(this.status === PENDING){             this.status = FULFILLED;             this.value = value;             while(this.fulfilledCallback.length){                 this.fulfilledCallback.shift()()             }         }     }     reject = (reason)=>{         if(this.status === PENDING){             this.status = REJECTED;             this.reason =reason;             while(this.rejectedCallback.length){                 this.rejectedCallback.shift()()             }         }     }     then = (fulfilled,rejected)=>{         fulfilled = fulfilled ? fulfilled :value=>value;         rejected = rejected ? rejected :reason=>{throw reason};         const promise2 = new MyPromise((resolve,reject)=>{              if(this.status === FULFILLED){                 setTimeout(()=>{                     try{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)             }             else if(this.status === REJECTED){                 setTimeout(()=>{                     try{                         const x = rejected(this.reason)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)             }             else{                 this.fulfilledCallback.push(()=>{                       setTimeout(()=>{                     try{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)                 })                 this.rejectedCallback.push(()=>{                      setTimeout(()=>{                     try{                         const x = rejected(this.reason)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)                 });             }         })                 return promise2     } } function resolvePromise(promise2,x,resolve,reject){     if(promise2 === x){        return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))     }     if(x instanceof MyPromise){         x.then(value=>resolve(value),reason=>reject(reason))     }     else{         resolve(x)     } } function p1(){     return new MyPromise((resolve,reject)=>{         setTimeout(()=>{             resolve('p1')         },2000)     }) } function p2(){     return new MyPromise((resolve,reject)=>{         resolve('p2')     }) } MyPromise.all(['a','b',p1(),p2(),'c']).then(value=>{     console.log(value) }) 复制代码

Promise.resolve

Promise.resolve会将接受到的数字转换为一个promise对象返回,如果传入的就是一个promise对象则会原封不动的返回

const PENDING = 'pening' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise{     status = PENDING;     value = undefined;     reason = undefined;     fulfilledCallback = [];     rejectedCallback = [];     static resolve(value){         //判断data的类型,如果是promise类型的则原封不动的返回         if(value instanceof MyPromise){             return value         }         //如果是普通类型的则转换为promise对象返回         else{             return new MyPromise((resolve,reject)=>{                 resolve(value)             })         }     }     static all(arr){         return new MyPromise((resolve,reject)=>{             let result = [];             let resultIndex = 0;             arr.forEach((item,index)=>{                 if(item instanceof MyPromise){                     item.then(value=>{                         result[index] = value;                         resultIndex++;                         if(resultIndex === arr.length){                             resolve(result)                         }                       },reason=>reject(reason))                 }                 else{                     result[index] = item;                     resultIndex++;                     if(resultIndex === arr.length){                         resolve(result)                     }                   }                             })         })            }     constructor(executor){         try{             executor(this.resolve,this.reject)         }         catch(err){             this.reject(err)         }     }     resolve = (value)=>{         if(this.status === PENDING){             this.status = FULFILLED;             this.value = value;             while(this.fulfilledCallback.length){                 this.fulfilledCallback.shift()()             }         }     }     reject = (reason)=>{         if(this.status === PENDING){             this.status = REJECTED;             this.reason =reason;             while(this.rejectedCallback.length){                 this.rejectedCallback.shift()()             }         }     }     then = (fulfilled,rejected)=>{         fulfilled = fulfilled ? fulfilled :value=>value;         rejected = rejected ? rejected :reason=>{throw reason};         const promise2 = new MyPromise((resolve,reject)=>{              if(this.status === FULFILLED){                 setTimeout(()=>{                     try{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)             }             else if(this.status === REJECTED){                 setTimeout(()=>{                     try{                         const x = rejected(this.reason)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)             }             else{                 this.fulfilledCallback.push(()=>{                       setTimeout(()=>{                     try{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)                 })                 this.rejectedCallback.push(()=>{                      setTimeout(()=>{                     try{                         const x = rejected(this.reason)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)                 });             }         })                 return promise2     } } function resolvePromise(promise2,x,resolve,reject){     if(promise2 === x){        return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))     }     if(x instanceof MyPromise){         x.then(value=>resolve(value),reason=>reject(reason))     }     else{         resolve(x)     } } function p1(){     return new MyPromise((resolve,reject)=>{         setTimeout(()=>{             resolve('p1')         },2000)     }) } function p2(){     return new MyPromise((resolve,reject)=>{         resolve('p2')     }) } MyPromise.resolve('a').then(value=>{     console.log(value) }) MyPromise.resolve(p1()).then(value=>{     console.log(value) }) 复制代码

finally方法

无论promise的状态如何finally中的代码都会执行,他接受一个函数参数。返回一个promise对象。

const PENDING = 'pening' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise{     status = PENDING;     value = undefined;     reason = undefined;     fulfilledCallback = [];     rejectedCallback = [];     static resolve(data){         //判断data的类型,如果是promise类型的则原封不动的返回         if(data instanceof MyPromise){             return data         }         //如果是普通类型的则转换为promise对象返回         else{             return new MyPromise((resolve,reject)=>{                 resolve(data)             })         }     }     static all(arr){         return new MyPromise((resolve,reject)=>{             let result = [];             let resultIndex = 0;             arr.forEach((item,index)=>{                 if(item instanceof MyPromise){                     item.then(value=>{                         result[index] = value;                         resultIndex++;                         if(resultIndex === arr.length){                             resolve(result)                         }                       },reason=>reject(reason))                 }                 else{                     result[index] = item;                     resultIndex++;                     if(resultIndex === arr.length){                         resolve(result)                     }                   }                             })         })            }     finally = (callback)=>{         //无论什么样的状态都要执行回调函数,借助then方法在成功和失败的回调中都调用callback         //finally返回一个promise对象,该对象的状态为调用finally的对象的状态,其实就是then方法的返回值。         return this.then(value=>{             // callback()             // //传递给下一个then方法的参数为then方法相应状态的参数             // return value             //如果遇到异步任务,需要等到异步结果再把结果返回回去,可以借助上面写的resolve方法,讲callback得结果转为promise对象,在状态改变之后返回回去            return MyPromise.resolve(callback()).then(()=>value)         },reason=>{             // callback()             // //传递给下一个then方法的参数为then方法相应状态的参数,失败状态需要通过throw改变状态为reject。             // throw reason               //如果遇到异步任务,需要等到异步结果再把结果返回回去,可以借助上面写的resolve方法,讲callback得结果转为promise对象,在状态改变之后返回回去              return MyPromise.resolve(callback()).then(()=>{throw reason})         })     }     constructor(executor){         try{             executor(this.resolve,this.reject)         }         catch(err){             this.reject(err)         }     }     resolve = (value)=>{         if(this.status === PENDING){             this.status = FULFILLED;             this.value = value;             while(this.fulfilledCallback.length){                 this.fulfilledCallback.shift()()             }         }     }     reject = (reason)=>{         if(this.status === PENDING){             this.status = REJECTED;             this.reason =reason;             while(this.rejectedCallback.length){                 this.rejectedCallback.shift()()             }         }     }     then = (fulfilled,rejected)=>{         fulfilled = fulfilled ? fulfilled :value=>value;         rejected = rejected ? rejected :reason=>{throw reason};         const promise2 = new MyPromise((resolve,reject)=>{              if(this.status === FULFILLED){                 setTimeout(()=>{                     try{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)             }             else if(this.status === REJECTED){                 setTimeout(()=>{                     try{                         const x = rejected(this.reason)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)             }             else{                 this.fulfilledCallback.push(()=>{                       setTimeout(()=>{                     try{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)                 })                 this.rejectedCallback.push(()=>{                      setTimeout(()=>{                     try{                         const x = rejected(this.reason)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)                 });             }         })                 return promise2     } } function resolvePromise(promise2,x,resolve,reject){     if(promise2 === x){        return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))     }     if(x instanceof MyPromise){         x.then(value=>resolve(value),reason=>reject(reason))     }     else{         resolve(x)     } } function p1(){     return new MyPromise((resolve,reject)=>{         setTimeout(()=>{             resolve('p1')         },2000)     }) } function p2(){     return new MyPromise((resolve,reject)=>{         resolve('p2')     }) } const promise1 = new MyPromise((resolve,rejct)=>{     resolve(1) }).finally(()=>{     console.log("finally执行了")    return p1() }).then(value=>{     console.log(value) }) 复制代码

catch方法

catch方法接受一个失败的处理回调函数,用于失败状态的处理操作,并且可以继续使用then方法,所以他的返回值为promise对象

const PENDING = 'pening' const FULFILLED = 'fulfilled' const REJECTED = 'rejected' class MyPromise{     status = PENDING;     value = undefined;     reason = undefined;     fulfilledCallback = [];     rejectedCallback = [];     static resolve(data){         //判断data的类型,如果是promise类型的则原封不动的返回         if(data instanceof MyPromise){             return data         }         //如果是普通类型的则转换为promise对象返回         else{             return new MyPromise((resolve,reject)=>{                 resolve(data)             })         }     }     static all(arr){         return new MyPromise((resolve,reject)=>{             let result = [];             let resultIndex = 0;             arr.forEach((item,index)=>{                 if(item instanceof MyPromise){                     item.then(value=>{                         result[index] = value;                         resultIndex++;                         if(resultIndex === arr.length){                             resolve(result)                         }                       },reason=>reject(reason))                 }                 else{                     result[index] = item;                     resultIndex++;                     if(resultIndex === arr.length){                         resolve(result)                     }                   }                             })         })            }     finally = (callback)=>{         return this.then(value=>{            return MyPromise.resolve(callback()).then(()=>value)         },reason=>{              return MyPromise.resolve(callback()).then(()=>{throw reason})         })     }     catch = (fallBack)=>{         //调catch方法会执行失败的操作,返回promise对象。         return this.then(undefined,fallBack)     }     constructor(executor){         try{             executor(this.resolve,this.reject)         }         catch(err){             this.reject(err)         }     }     resolve = (value)=>{         if(this.status === PENDING){             this.status = FULFILLED;             this.value = value;             while(this.fulfilledCallback.length){                 this.fulfilledCallback.shift()()             }         }     }     reject = (reason)=>{         if(this.status === PENDING){             this.status = REJECTED;             this.reason =reason;             while(this.rejectedCallback.length){                 this.rejectedCallback.shift()()             }         }     }     then = (fulfilled,rejected)=>{         fulfilled = fulfilled ? fulfilled :value=>value;         rejected = rejected ? rejected :reason=>{throw reason};         const promise2 = new MyPromise((resolve,reject)=>{              if(this.status === FULFILLED){                 setTimeout(()=>{                     try{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)             }             else if(this.status === REJECTED){                 setTimeout(()=>{                     try{                         const x = rejected(this.reason)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)             }             else{                 this.fulfilledCallback.push(()=>{                       setTimeout(()=>{                     try{                         const x = fulfilled(this.value)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)                 })                 this.rejectedCallback.push(()=>{                      setTimeout(()=>{                     try{                         const x = rejected(this.reason)                         resolvePromise(promise2,x,resolve,reject)                     }                     catch(err){                         reject(err)                     }                  },0)                 });             }         })                 return promise2     } } function resolvePromise(promise2,x,resolve,reject){     if(promise2 === x){        return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))     }     if(x instanceof MyPromise){         x.then(value=>resolve(value),reason=>reject(reason))     }     else{         resolve(x)     } }


作者:木十八z
链接:https://juejin.cn/post/7030698739551436830


文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐