当前位置: 首页 > 后端技术 > PHP

如何实现Promise的实例方法和静态方法

时间:2023-03-29 20:46:53 PHP

Promise是一种异步编程的解决方案,比传统的回调函数或事件更加合理和灵活。本文主要展示Promise提供的方法列表,以及基本的实现原理。通过本文,我们可以加深对Promise方法的理解和使用,对Promise.all、Promise.race、Promise.allSettled和Promise.any这四种方法的异同有更深刻的理解。1.Promise方法列表Promise有3个实例方法:then/catch/finally,6个静态方法:all/race/allSettled/any/resolve/reject。其中then的实现会比较复杂,因为涉及到PromiseResolutionProcedure(承诺解决程序),其余都是基于现有功能的扩展。下面列出了所有方法。Promise.prototype.then()Promise.prototype.catch()Promise.prototype.finally()Promise.all()Promise.race)Promise.allSettled)Promise.any()Promise.resolve()Promise.reject()二9Promise实现1.原型方法then方法是整个Promise解决方案的核心内容,由于回调函数和返回一个新的Promise实例,解决过程比较复杂。//类MyPromise{//staticPENDING='pending';//进行中//staticFULFILLED='fulfilled';//成功//staticREJECTED='rejected';//失败//state=MyPromise.PENDING;//value=null;//reason=null;//onFulfilledCallbacks=[];//onRejectedCallbacks=[];//...//}MyPromise.prototype.then=(onFulfilled,onRejected)=>{if(typeofonFulfilled!='function'){onFulfilled=(value)=>value;}if(typeofonRejected!='function'){onRejected=(reason)=>{throwreason;};}//Promise核心解析过程参考规范2.3const_resolvePromise=(promise,x,resolve,reject)=>{//2.3.1如果promise和x指向同一个对象,则抛出TypeError错误if(promise===x){consterrMsg='promise和返回值相同';返回拒绝(新类型错误(errMsg));}//2.3.3如果x是对象(不为空)或函数if((typeofx==='object'&&x!==null)||typeofx==='function'){letthen=努二;尝试{//2.3.3.1。检索属性x.thenthen=x.then;}catch(error){//2.3.3.2如果x.then导致抛出异常e,则拒绝以e为拒绝原因的promisereturnreject(error);}//2.3.3.3如果then是一个函数,x作为then的this调用方法,第一个参数是成功的回调函数,第二个参数是失败的回调函数if(typeofthen==='函数'){让调用=false;try{then.call(x,(y)=>{//2.3.3.3.4如果成功回调和失败回调都被调用或者多次调用同一个参数,第一次调用优先,其他所有调用将被忽略if(called)return;called=true;//2.3.3.3.1如果使用值y调用成功回调,运行[[Resolve]](promise,y)_resolvePromise(promise,y,resolve,reject);},(r)=>{//2.3.3.3.4如果成功回调和失败回调都被调用或者多次调用同一个参数,第一次调用优先,其他调用将被忽略。如果(称为)返回;称为=真;//2.3.3.3.2如果因原因r调用失败回调,则使用rreject(r)拒绝promise;});}catch(error){//2.3.3.4ifcalledthen方法抛出异常e://2.3.3.4.1如果调用成功回调或失败回调,则忽略if(called)return;//2.3.3.4.2未调用,使用e作为拒绝承诺的原因reject(error);}}else{//2.3.3.4。如果then不是函数,则以x为值完成promisereturnresolve(x);}}else{//2.3.4如果x不是对象或函数,则使用x作为参数Executepromisereturnresolve(x);}};//链式返回的PromiseconstnewPromise=newMyPromise((resolve,reject)=>{switch(this.state){caseMyPromise.FULFILLED:setTimeout(()=>{try{constx=onFulfilled(this.value);_resolvePromise(newPromise,x,resolve,reject);}catch(reason){reject(reason);}},0);中断;caseMyPromise.REJECTED:setTimeout(()=>{try{constx=onRejected(this.reason);_resolvePromise(newPromise,x,resolve,reject);}catch(reason){reject(reason);}},0);休息;caseMyPromise.PENDING:this.onFulfilledCallbacks.push(()=>{setTimeout(()=>{try{constx=onFulfilled(this.value);_resolvePromise(newPromise,x,resolve,reject);}catch(原因){拒绝(原因);}},0);});this.onRejectedCallbacks.push(()=>{setTimeout(()=>{try{constx=onRejected(this.reason);_resolvePromise(newPromise,x,resolve,reject);}catch(reason){reject(reason));}},0);});休息;}});返回新承诺;};2。原型方法catch如果上面如果没有定义reject方法或者抛出错误,所有的异常都会转到catch方法,catch可以复用then方法MyPromise.prototype.catch=function(onRejected){returnthis.then(null,onRejected);};3。finally原型方法不管是resolve还是reject都会调用finally。那么就相当于finlly方法为用户分别调用了then的resolved和rejected状态回调。MyPromise.prototype.finally=function(fn){returnthis.then((value)=>{fn();returnvalue;},(reason)=>{fn();throwreason;});};4.静态方法Promise.allPromise.all()方法用于将多个Promise实例包装成一个新的Promise实例。对所有参数数组Promise实例执行完resolve回调后,新实例执行resolve回调;如果中间有任何一个Promise实例执行了reject回调,则新实例直接执行reject回调。比如:多个员工同时在做多个项目,你要求任何一个项目都必须让你满意。如有一处不满意,视为本次活动(所有项目)失败。重点是整体满意度。MyPromise.all=function(promises){returnnewPromise((resolve,reject)=>{if(promises.length===0){resolve([]);}else{letresult=[];letindex=0;for(leti=0;i{result[i]=data;if(++index===promises.length){resolve(result);}},(err)=>{reject(err);return;});}}});};5.静态方法Promise.racePromise.race()顾名思义,就是一个赛跑,返回最Almost完整的那个Promise实例。只要参数数组中有执行resolve回调或reject回调的Promise实例,新实例就会直接返回结果。例如:多个员工同时在做多个项目,而你只想要最快完成的项目,不管这个项目是否让你满意。重点是要快。MyPromise.race=function(promises){returnnewPromise((resolve,reject)=>{if(promises.length===0){resolve();}else{letindex=0;for(leti=0;i{resolve(data);},(err)=>{reject(err);return;});}}});};6。静态方法Promise.allSettledPromise.allSettled()方法只有当参数数组中的所有Promise实例都有状态变化时,返回的Promise实例才会发生状态变化,无论是执行resolve回调还是reject回调的状态。比如:多个员工同时在做多个项目,你要求每个项目都必须完成,然后得到所有的项目是让你满意还是让你不满意。重点是最终结果。MyPromise.allSettled=function(promises){returnnewPromise((resolve,reject)=>{if(promises.length===0){resolve([]);}else{letresult=[];letindex=0;for(leti=0;i{result[i]={status:'fulfilled',value,};},(reason)=>{result[i]={status:'rejected',reason,};}).finally(()=>{if(++index===promises.length){returnresolve(result);}});}}});};同时,由于Promise.allSettled()和Promise.all()是对所有Promise实例的一种处理,下面可以使用Promise.all()来实现Promise.allSettled()方法。MyPromise.allSettled=function(promises){returnPromise.all(promises.map((item)=>Promise.resolve(item).then((value)=>({status:'fulfilled',value}),(reason)=>({status:'rejected',reason})));};7.静态方法Promise.anyPromise.any()返回最快执行resolve回调的任何Promise实例。例如:多个员工是同时做多个项目,只要你最快拿到让你满意的项目,不管最后所有项目是否都不能让你满意,这件事(所有项目)都算失败。开得又快又好。MyPromise.any=function(promises){returnnewPromise((resolve,reject)=>{if(promises.length===0){returnresolve();}else{letresult=[];letindex=0;for(leti=0;i{returnresolve(value);},(reason)=>{result[i]=reason;if(++index===promises.length){returnreject(newAggregateError(result));}});}}});};8.静态方法Promise.resolvePromise.resolve方法返回给定的APromise实例,其值为resolved。相当于在then方法中执行了_resolvePromise。MyPromise.reject=function(value){returnnewMyPromise((resolve,reject)=>{resolve(value);});};9.静态方法Promise.rejectPromise.reject方法返回一个带有拒绝原因的Promise实例。我的承诺。reject=function(reason){returnnewMyPromise((resolve,reject)=>{reject(reason);});};