1.Promise/A+规范①Promise是一个类或函数,有3种内部状态,即pending(等待)、fulfilled(执行、完成)、rejected(拒绝、未完成)。默认是pending状态,即Promise对象在第一次创建时的状态是pending,pending状态可以转换为fulfilled或者rejected。已完成和已拒绝是最终状态。一旦完成或被拒绝,将无法更改为其他状态。②Promise需要对外提供then方法。如果可选参数onFulfilled和onRejected不是函数,则应忽略promise.then(onFulfilled,onRejected);onFulfilled和onRejected函数都应该异步执行;onFulfilled函数调用时,会将当前Promise的值作为参数传入,并且只能调用一次;调用onRejected函数时,会将当前Promise的失败原因作为参数传入,并且只能调用一次;then函数的返回值对于链式调用仍然是Promise;③resolvePromisethen方法会创建并返回一个Promise对象,then中注册的回调函数会返回各种值,必须进行验证。then方法返回的promise不能等于then中回调函数的返回值x,否则需要抛出错误;如果then回调函数的返回值是非Promise对象,那么直接使用then返回的promise对象的resolve方法,resolve(x)即可。如果then回调函数的返回值x是一个Promise对象或者是一个带有then方法的对象或函数,那么就需要执行它的then方法来注册回调,获取Promise或者Promise-like对象的值作为然后返回promise的值,如果该值仍然是Promise对象则需要递归操作;2、实现Promise①根据第一个规范,Promise是一个类或者函数,所以我们先将Promise定义为一个类,内部状态有3种,我们定义为常量。varPENDING="pending";//等待状态varFULFILLED="fulfilled";//执行,完成状态varREJECTED="rejected";//拒绝,未完成状态classPromise{constructor(){this.state=PENDING;//PromiseAfter对象创建完成,默认处于等待状态}??}②我们在创建Promise的时候,会传入一个函数,这个函数会在Promise对象创建的时候立即执行,并且会接收两个参数,用于分别执行或拒绝当前Promise对象,即修改当前Promise对象的状态。Promise用于异步处理,所以当Promise状态变成完成时,可能会收到异步操作执行的结果,当Promise状态变成未完成时,可能会收到失败原因,所以Promise里面需要保存。异步操作的结果值和失败的原因。......classPromise{constructor(executor){//传入执行器函数......this.value=undefined;//保存异步操作的结果this.reason=undefined;//保存failedReasonconstresolve=(value)=>{this.value=value;this.state=FULFILLED;//改变Promise对象的状态为完成状态}constreject=(reason)=>{this.reason=reason;this.state=REJECTED;//将Promise对象的状态改为未完成状态}try{executor(resolve,reject);//executor是用户传入的,可能会出错,需要捕获}catch(e){reject(e);}}}③这里还有一个问题,就是Promise必须执行一次。Promise的状态一旦从pending变成fulfilled或者rejected,就不能再改变,也不允许从fulfilled变成fulfilled。也就是说resolve或者reject只能执行一次。所以我们需要判断resolve和reject的内部结构。如果状态发生了变化,则不再执行,如:......classPromise{constructor(executor){//执行器函数介绍......constresolve=(value)=>{if(this.state===PENDING){//防止用户多次解析,以第一个解析为准...}}constreject=(reason)=>{if(this.state===PENDING){//防止用户多次拒绝...}}...}}④在Promise中添加一个then函数,then函数接收两个onFulfilled和onRejected函数作为参数,用于处理when的回调函数Promise完成和未完成的时间。如果不是函数,则必须初始化为函数,如:classPromise{then(onFulfilled,onRejected){onFulfilled=typeofonFulfilled==="function"?onFulfilled:(value)=>{//如果onFulfilled是notafunction,initializeacompletionhandlerreturnvalue;};onRejected=typeofonRejected==="function"?onRejected:(reason)=>{//如果onRejected不是function,初始化一个unfulfilled处理函数throwreason;//Throwwhateverpassed}}}⑤Then方法其实就是一个注册回调的过程。当随后调用的Promise对象状态变为完成状态时,可以执行onFulfilled回调函数,当Promise对象状态变为rejected时,可以执行onRejected回调函数。所以回调函数的执行取决于当时调用的Promise的状态。同时为了支持链式调用,then方法也需要返回一个Promise对象。按照之前的Promise规范,传入的回调函数必须异步执行,这里用setTimeout来模拟。classPromise{then(onFulfilled,onRejected){......letpromise;switch(this.state){caseFULFILLED://当then方法被调用时,当前Promise状态已经变成完成状态,回调可以完成后立即执行Functionpromise=newPromise((resolve,reject)=>{setTimeout(()=>{try{letx=onFulfilled(this.value);}catch(e){console.log(e);//打印错误消息reject(e);}});});break;caseREJECTED:promise=newPromise((resolve,reject)=>{setTimeout(()=>{try{letx=onRejected(this.reason);}catch(e){reject(e);}});}break;casePENDING:promise=newPromise((resolve,reject)=>{//TODO});break;}returnpromise;}}⑥当Promise对象调用then处于pending状态,此时通过then注册的回调函数并不能立即执行,注册的回调函数必须等待Promise的状态变为final状态,这就涉及到一个发布订阅模型,我们可以先保存回调函数,然后Promise什么时候变成fina我状态?也就是调用resolve或者reject的时候,所以我们可以把注册的回调函数取出来,在调用resolve或者reject的时候执行。classPromise{constructor(executor){constresolve=(value)=>{if(this.state===PENDING){//防止用户多次解析,以第一次解析为准......this.onFulfilleds。forEach(fn=>fn());//取出then中注册的完成回调函数执行}};constreject=(reason)=>{if(this.state===PENDING){//阻止用户来自运行过多的reject......this.onRejecteds.forEach(fn=>fn());//取出then中注册的拒绝回调函数并执行}};}then(onFulfilled,onRejected){.....switch(this.state){casePENDING:promise=newPromise((resolve,reject)=>{this.onFulfilleds.push(()=>{try{letx=onFulfilled(this.value);}catch(e){console.log(e);//打印错误信息reject(e);}});this.onRejecteds.push(()=>{try{letx=onRejected(this.reason);}catch(e){reject(e);}});});break;}}}⑦接下来就是处理这时注册的回调函数的返回值,因为回调函数的返回值可能是在各种情况下,它m可能是普通的值,可能是Promise对象,也可能是带有then方法的对象,所以我们要一一处理。这里我们使用一个单独的方法resolvePromise()来处理各种情况,比如//传入then()方法中创建的Promise对象,回调函数的返回值x,以及then中创建的Promise的resolve()method、rejectconstresolvePromise=function(promise,x,resolve,reject){//TODO}classPromise{constructor(executor){//引入执行函数...}then(onFulfilled,onRejected){caseFULFILLED:promise=newPromise((resolve,reject)=>{......letx=onFulfilled(this.value);resolvePromise(promise,x,resolve,reject);//处理回调函数的返回值});caseREJECTED:promise=newPromise((resolve,reject)=>{......letx=onRejected(this.reason);resolvePromise(promise,x,resolve,reject);//处理回调函数的返回值});casePENDING:this.onFulfilleds.push(()=>{letx=onFulfilled(this.value);resolvePromise(promise,x,resolve,reject);//处理回调函数的返回值});this.onRejecteds。push(()=>{letx=onRejected(this.reason);resolvePromise(promise,x,resolve,reject);//处理回调函数的返回值});}}3.实现resolvePromise①如果返回值回调函数的和then()方法中创建的Promise对象相同,就会抛出错误,相当于等待自己进入死循环。letp1=newPromise((resolve,reject)=>{resolve(1);})letp2=p1.then((value)=>{//p2是then方法returnp2中创建的Promise对象;});//结果抛出错误,显示Chainingcycledetectedforpromise#
