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,所以会报错。
创建的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