在开始之前,Promise的实现原理已经在PromiseSpecificationInterpretationandImplementationDetails(1)中说的很清楚了。这里,我们将详细分析Promises/A+规范中的Promise解析过程,最终实现一个Promise并提供代码进行测试。then方法分析promise.then(fn1).then(fn2).then(fn3)其中对promise.then()的调用将为then(fn).作为参数传递给fnforthen(fn)ifthen返回一个promise1并且fn返回一个promise2那么promise1的状态和值由promise2决定forthen(fn)ifthen返回一个promise1并且fn返回一个我们想要的promise2依赖promise2的调用会添加到promise1中。如何让promise2决定promise1的结果?Promise的resolve和reject都变了,所以只需要通过promise2的then方法将promise1的这两个函数添加到promise2的执行队列中,就可以达到想要的效果。Promise解析过程为promise.then(fn),then方法返回promise1,fn方法返回x,fn接收的参数为y。这时需要分别在x和y上运行Promise解析过程。x:[[Resolve]](promise1,x)y:[[Resolve]](promise1,y)x的解析过程处理回调中返回promise的情况。y的解析过程处理的是将处理结果传递给当前promise的promise的最终值为promise的情况。可以看出promise的解析过程是递归的,递归的终点是x,y不是promise,在对象或者函数的情况下没有then方法代码结构(function(window){varPENDING=0;//PENDING状态varRESOLVED=1;//RESOLVED状态varREJECTED=2;//REJECTED状态functionIPromise(fn){if(!(thisinstanceofIPromise))returnnewIPromise(fn);//确保newIPromise()和IPromise()都能正确创建对象varstate=PENDING;//promisestatevarvalue=null;//finalvaluevarcallback=[];//返回函数队列,一个是两个队列,这里是一个,所以存储对象functionreject(reason){}//reject方法functionresolve(result){}//和(1)相比,这个,还有更多函数执行Promise解析过程functionhandle(handler){}//在teamcallback中添加或执行调用/***@paramonFulfilledonFulfilled通过then方法添加*@paramonRejectedonRejected通过then方法添加方法**@func包装用户添加的回调*因为这里只有一个回调队列,所以需要用糖果(candy)包装成{onFulfilled:onFulfilled,onRejected:onRejected}**@func延迟调用句柄*Promise规范的解释和实现细节(1)据说Promise(浏览器实现)将被添加到microtask中。由于浏览器没有提供除Promise*以外的microtask接口,所以我们需要使用setTimeout延迟调用,加入macrotask**/functioncandy(onFulfilled,onRejected){}functiongetThen(value){}//判断value是否有then方法,有则getthis。then=function(onFulfilled,onRejected){}//暴露的then方法doResolve(fn,resolve,reject);//执行fnwindow.IPromise=IPromise;//在浏览器窗口添加IPromise}/***Promise解析过程*/functiondoResolve(fn,resolvePromise,rejectPromise){}//静态私有方法,resolve并执行promise(解析并执行fn和promise的处理结果)})(窗户);上面通过js自执行函数将变量和函数限制在全局窗口中,只暴露一个构造函数IPromise,保证全局不被污染。具体代码及解释(请在浏览器中运行)/***@authorivenj*@date2016-12-06*@version1.0*/(function(window){varPENDING=0;varRESOLVED=1;varREJECTED=2;functionIPromise(fn){if(!(thisinstanceofIPromise))returnnewIPromise(fn);varstate=PENDING;varvalue=null;varcallback=[];functionreject(reason){state=拒绝;value=原因;回调.forEach(句柄);回调=空;/***这里新增的内容是在Promise解析过程满足时,resolve和doResolve相互调用形成递归**/functionresolve(result){try{varthen=getThen(result);if(then){doResolve(then.bind(result),resolve,reject);//aa返回;//这里,如果resule有then方法,则执行doResolve,不执行后续代码就返回}//只有当结果不满足解析过程时才执行,即递归结束状态=RESOLVED;价值=结果;回调.forEach(句柄);回调=空;}抓住(e){拒绝(e);}}functionhandle(handler){if(state===PENDING){callback.push(handler);}else{if(state===RESOLVED&&typeofhandler.onFulfilled==='function'){处理程序。onFulfilled(价值);}if(state===REJECTED&&typeofhandler.onRejected==='function'){handler.onRejected(value);}}}functioncandy(onFulfilled,onRejected){setTimeout(function(){handle({onFulfilled:onFulfilled,onRejected:onRejected});},0);}functiongetThen(value){vartype=typeofvalue;if(value&&(type==='object'||type==='function')){try{varthen=value.then;}赶上(e){拒绝(e);}if(typeofthen==='function'){然后返回;}}返回空值;}this.then=function(onFulfilled,onRejected){varself=t他的;returnnewIPromise(function(resolve,reject){candy(function(x){if(typeofonFulfilled==='function'){try{resolve(onFulfilled(x));//cc运行[[Resolve]](promise,x)}catch(e){reject(e);}}else{resolve(x);}},function(error){if(typeofonRejected==='function'){尝试{resolve(onRejected(error));}catch(e){reject(e);}}else{reject(error);}});});};doResolve(fn,解决,拒绝);}/***Promise解析过程*/functiondoResolve(fn,resolvePromise,rejectPromise){vardone=false;//用于确保只有一次调用](promise,y)},function(reason){if(done)return;done=true;rejectPromise(reason);});}catch(e){如果(完成)返回;完成=真;拒绝承诺(e);}}window.IPromise=IPromise;})(窗口);下面是测试代码读者将上面的代码和下面的代码粘贴到浏览器中运行一秒后会打印{url:"http://ivenj_",value:10}functionpost(url,callback){setTimeout(function(){vardata={//模拟异步处理结果url:url,value:10};callback(data);},1000);}varpromise=IPromise(function(resolve,reject){post('http://ivenj_',function(data){resolve(data);});});承诺.thzh(函数(数据){console.log(数据);});Promise实现的核心内容在代码中//aa//bb//cc读者需要重点理解这三个Promise,到此结束
