关注前端小鱼,阅读更多原创技术文章回顾:Promise源码渐进解读(一)回顾:Promise源码渐进解读(二)完整代码+评论,可以阅读Promise.prototype.then——sourcecode/**Promise原型的then属性,指向函数*参数onFulfilled:onResolvedhandler,合约履行时执行的回调*参数onRejected:onRejectedhandler,合约被拒绝时执行的回调*支持infinite链式回调,每个then()方法返回一个新的Promise实例*/Promise.prototype.then=function(onFulfilled,onRejected){//console.log(this,'then')//this指向之前返回的Promise实例然后()//控制台。log(this.constructor)//构造函数指向Promise构造函数//console.log(this.constructor===Promise)//true/*创建一个新的合约实例(相当于newPromise(noop)),传入空方法noop作为执行函数注意:每次调用.then()都会创建一个新的Promise实例,但是调用下一个.then()会改变前一个Promise实例的_deferreds数组(变成下一个Handler实例)!*/varprom=newthis.constructor(noop)//->varprom=newPromise(noop)->varprom=newPromise(()=>{})//console.log(prom)//Promise{_state:0,_handled:false,_value:undefined,_deferreds:[]},newpromise//console.log(newPromise(noop))//Promise{_state:0,_handled:false,_value:undefined,_deferreds:[]},同上/***handle()方法*参数this:then()之前返回的最后一个Promise实例*参数newHandler(onFulfilled,onRejected,prom):创建的Handler实例*/handle(this,newHandler(onFulfilled,onRejected,prom))returnprom//返回新创建的合约实例,从而链式调用}functionnoop(){}then在this指向的函数中指向当前then之前返回的Promise实例,因此this.constructor指向Promise构造函数。每次调用Promise.then时:使用空方法noop作为执行函数,调用newthis.constructor()创建一个新的空Promise实例,同时创建一个新的Handler实例,然后调用handle()方法最终返回新建合约实例,支持无限链式回调“调用下一个.then()会改变上一个Promise实例的_deferreds数组”,后面可以研究Handler构造函数-源码/**Handler构造函数:packageonFulfilled,onRejected和promise,作为一个整体方便后续调用*参数onFulfilled:解析回调函数*参数onRejected:拒绝回调函数*参数promise:新建空promise实例*/functionHandler(onFulfilled,onRejected,promise){this.onFulfilled=typeofonFulfilled==='函数'?onFulfilled:null//是否有成功的回调,如果没有,则设置为nullthis.onRejected=typeofonRejected==='function'?onRejected:null//是否有失败回调,没有则为null。this.promise=promise//Handler的promise指向prom,也就是.then()中新建的Promiseinstance//console.log(this.promise,'newHandler')//console.log(this)}接收3个参数:成功回调,失败回调newemptypromiseinstancehandle()-测试代码在源码中code在精简的基础上,方便做阶段测试/**handle()方法用于测试*参数self:then()之前返回的Promise实例*参数deferred:创建的Handler实例*/functionhandle(self,deferred){//console.log(self)//console.log(deferred)/*deferred是创建的Handler实例Handler{onFulfilled:[Function(anonymous)],//onFulfilledhandler,nullifnotonRejected:[Function(anonymous)],//onRejectedhandler,nullifnonepromise:Promise{//promise属性指向一个新的Promise实例_state:0,_handled:false,_value:undefined,_deferreds:[]}}*//*If返回的合约实例的解析值为promise类型,_state=3*/while(self._state===3){self=self._value//assigntheresolutionvaluetothereturnedcontractinstance}/*if返回的合约实例处于pending状态,_state=0,即resolve()或reject()方法还没有执行*/if(self._state===0){self._deferreds.push(deferred)//将Handler实例放入实例的_deferreds数组中,然后返回,继续等待console.log(self)return}/*mark当前的承诺._handledistrue*/self._handled=trueconsole.log(self)/*通过事件循环异步处理回调(注意:这是异步的!)*/Promise._immediateFn(function(){varcb=self._state===1?deferred.onFulfilled:deferred.onRejected//获取onFulfilled或onRejectedhandler/*如果有onFulfilled或onRejected回调函数,执行你自己的回调*/try{/***cb()method:ExecuteonFulfilled或onRejectedhandler*参数self._value:then()/rejectionreason之前返回的Promise实例的解析值*/cb(self._value)//执行回调}catch(e){/*如果抛出错误,调用reject()方法,参数为创建的Handler实例的promise(newPromise实例)和错误原因*/reject(deferred.promise,e)return}})}然后根据返回合约实例to状态值不同,做不同的处理返回非挂起的合约,最后执行handlerinthen返回挂起的合约,那么then中的handler不会被执行,但是then中生成的Handler实例会放在进入then之前的Promise实例的_deferreds数组中异步执行then中的handler,并执行Promise.prototype.then在所有同步操作执行完后-stagetestnewPromise((resolve,reject)=>{}).then(()=>{console.log(3)//then之前是一个未解析的合约,andhandler不会被执行,直到合约被resolved})/*handle()执行时,self._state为0,将Handler实例放入实例的_deferreds数组中,不会再进行任何操作,self为:承诺{_state:0,_handled:false,_value:undefined,_deferreds:[Handler{onFulfilled:[Function(anonymous)],onRejected:null,promise:Promise{_state:0,_handled:false,_value:undefined,_deferreds:[]}}]}*/newPromise((resolve,reject)=>{/*第一次resolve或reject真正执行后,后面的resolve或reject不会再执行,这里只合并测试结果*/resolve(3)//打印res为3,resolvedvalue为基本类型/*self为Promise{_state:1,_handled:true,_value:3,_deferreds:[]}*/resolve({val:3})//printresas{val:3},resolvedvalue是一个普通对象/*self是一个Promise{_state:1,_handled:true,_value:{val:3},_deferreds:[]}*/resolve(newPromise(()=>{}))//不打印res,解析值为pending的futures实例/*self与newPromise((resolve,reject)=>{}).then()基本相同,onFulfilled不再是null*/resolve(Promise.resolve(3))//printresis3,theresolution值为fullfilled,并将fullfilled的resolution值赋给self/*selfisPromise{_state:1,_handled:true,_value:3,_deferreds:[]}*/resolve({//解析后的值为thenableobjectvalue:3,吨hen:function(){console.log(this)//{value:3,then:[Function:then]}console.log(this.value)//3},})/*selfandresolve(newPromise(()=>{}))同*/}).then((res)=>{console.log(res)//then()之前返回的Promise解析值})newPromise((resolve,reject)=>{reject(3)//打印res为3/*self为Promise{_state:2,_handled:true,_value:3,_deferreds:[]}*/}).then(null,(err)=>{console.log(err)//then()之前返回的Promise的拒绝原因})基本上有链式回调的原型:根据Promise实例的状态,得到它的解析值/拒绝原因,以及执行相应的handler的pedding状态(onResolve或onReject)调用then后,then中生成的Handler实例会被放入其_deferreds数组Promise.prototype.catch-sourcecode/**Promise原型的catch属性,指向函数*参数onRejected:onRejectedhandler,回调exec在合约被拒绝时调用*支持无限链式回调,每个catch()方法返回一个新的Promise实例*/Promise.prototype['catch']=function(onRejected){returnthis.then(null,onRejected)}做一个Promise.prototype.then上的封装层,仅接收onRejected处理程序Promise.prototype.catch-阶段测试newPromise((resolve,reject)=>{}).catch(()=>{console.log(3)//catch前未解决promise,handler在promise被resolved之前不会执行(同then)})newPromise((resolve,reject)=>{/*在第一个resolve或reject真正执行后,后面的resolve或reject不会执行再次执行,这里只合并测试结果*/reject(4)//4、拒绝的原因是基本类型/*selfisPromise{_state:2,_handled:true,_value:4,_deferreds:[]}*/reject({val:4})//{val:4},拒绝原因是一个普通对象/*self是一个Promise{_state:2,_handled:true,_value:{val:4},_deferreds:[]}*/throwError('error!')//'Error:error!',抛出错误/*selfisPromise{_state:2,_handled:true,_value:Error:error!,_deferreds:[]}*/reject(newPromise(()=>{}))//'Promise{_state:0,_handled:false,_value:undefined,_deferreds:[]}',合约本身作为原因forrejection(需要和resolve区分开来)/*selfisPromise{_state:2,_handled:true,_value:承诺{_state:0,_handled:false,_value:undefined,_deferreds:[]},_deferreds:[]}*/reject(Promise.resolve(3))//'Promise{_state:1,_handled:false,_value:3,_deferreds:[]}',如上,以期货合约本身作为拒绝原因,与期货合约状态/*selfisPromise{_state:2,_handled:true,_value:Promise{_state:1,_handled:false,_value:3,_deferreds:[]},_deferreds:[]}*/}).catch((err)=>{console.log(err)//在catch()之前返回的Promise被拒绝的原因})和Promise.prototype.then的结果大致相同。在catch的前期需要分清Promise被拒绝的原因。拒绝的原因是Promise实例。回调(多个尚未实现)代码截至本节→
