前言说到ES6,Promise是绕不开的问题;如果说ES6的Class是基于Javascript原型继承的封装,那么Promise就是对callback回调机制的改进。本文不谈Promise的实际应用;说说Promise实现的原理,从最简单的方案开始,一步步自己实现一个SimplePromise。入门文本从最简单的Promise初始化开始,使用:constpro=newPromise((res,rej)=>{})pro.then(data=>{},err=>{})Promise的构造函数是如上,需要传递一个函数作为参数,这个函数有两个变量:resolve、reject。而Promise有不同的执行状态,分为三种情况:Resolve、Reject、Pending。根据以上信息,写出最基本的SimplePromise类结构:/参数函数的作用域指向Class}_resolve(){}_reject(){}}接下来想想_resolve和_reject的函数。我们知道Promise是根据then方法执行回调,然后根据状态判断要执行的回调函数。不难推导出_resolve和_reject是根据handler的执行而改变状态的,状态只能由Pending转换为Reslove或Rejected,所以就有:classSimplePromise{constructor(handler){...}_resolve(val){//数据异步返回if(this._status==="PENDING"){//保证状态的不可逆性this._status="RESOLVED"this._value=val}}_reject(val){if(this._status==="PENDING"){this._status="REJECTED"this._value=val}}}然后调用逻辑下面我们分析一下then函数的逻辑,从调用开始:pro.then(data=>{},err=>{})然后接收两个参数,第一个是执行成功调用的函数,第二个是执行失败调用的函数。classSimplePromise{constructor(handler){...}_resolve(val){...}_reject(val){...}then(success,fail){switch(this._status){case"PENDING":中断;案例“已解决”:成功(this._value)中断;案例“REJECTED”:失败(this._value)中断;}}}上面实现了最简单的Promise测试代码:constpro=newSimplePromise(function(res,rej){letrandom=Math.random()*10if(random>5){res("success")}else{rej("fail")}})pro.then(function(data){console.log(data)},function(err){console.log(err)})当然这不能算是Promise.目前只实现了根据状态调用不同的回调函数。异步尚未实现。那么如何实现异步呢?关键在于then函数。判断_status为PENDING时,如何延迟调用success和fail函数,等待状态改变后再调用?支持异步。这里使用数组来存储失败和成功函数:.bind(this),this._reject.bind(this))}_resolve(val){if(this.status==="PENDING"){...lettempwhile(this._onSuccess.length>0){//依次执行onSuccess中的回调函数temp=this._onSuccess.shift()temp(val)}}}_reject(val){if(this.status==="PENDING"){...lettempwhile(this._onFail.length>0){temp=this._onFail.shift()temp(val)}}}then(success,fail){switch(this.status){case"PENDING":this._onSuccess.push(成功)this._onFail.push(失败)中断;...}}}使用onSuccess和onFail来存储回调函数。当处理状态为PENDING时,将回调函数推送到对应的数组中。当状态改变时,依次执行数组中的回调函数。测试代码:constpro=newSimplePromise(function(res,rej){setTimeout(function(){letrandom=Math.random()*10if(random>5){res("success")}else{rej("fail")}},2000)})pro.then(function(data){console.log(data)},function(err){console.log(err)})两秒后,对应回调为处决。至此,基本完成了最简单最简单的Promise骨架。但是还有很多功能需要完成。现在你可以休息一下,喝杯咖啡,抽点血,等我们回来的时候,继续让这无极骨架变得更丰满。.....ImprovePromise欢迎回来,让我们继续改进我们的Promise。上面已经完成了最基本的Promise,但是还远远不够。一是Promise需要实现链式调用,二是Promise还需要实现allraceresolvereject等静态函数。首先then的链式调用如何实现?然后需要返回的也是一个Promise。于是有了classSimplePromise{...then(success,fail){returnnewSimplePromise((nextSuccess,nextFail)=>{constonFullfil=function(val){constres=success(val)nextSuccess(res)}constonReject=函数(val){constres=fail(val)nextSuccess(res);}switch(this._status){case"PENDING":this._onSuccess.push(onFullfil)this._onFail.push(onReject)break;case"RESOLVED":onFullfil(this._value)break;case"REJECTED":onReject(this._value)break;}})}}测试代码:constsp=newSimplePromise(function(res,rej){setTimeout(function(){letrandom=Math.random()*10random>5?res(random):rej(random)},1000)})sp.then(data=>{console.log("超过5"+data)返回数据},err=>{console.log("小于5"+err)returnerr}).then((data)=>{console.log(data)})then的参数限制完成了链式调用,then方法还有很多其他的限制:考虑下面的问题:在代码中使用promise的四个语句之间区别在哪里?假设doSomething和doSomethingElse返回PromiseddoSomething().then(function(){returndoSomethingElse();}).then(finalHandler);doSomething().then(function(){doSomethingElse();}).then(finalHandler);;doSomething().then(doSomethingElse()).then(finalHandler);;doSomething().then(doSomethingElse).then(finalHandler);;答案一会揭晓,下面我们来梳理一下then方法对于传入不同类型参数的处理机制:直接代码:classSimplePromise{...then(success,fail){returnnewSimplePromise((nextSuccess,nextFail)=>{constonFullfil=function(val){if(typeofsuccess!=="function"){nextSuccess(val)}else{constres=success(val)//成功的返回值if(resinstanceofSimplePromise){//如果成功返回一个promise对象res.then(nextSuccess,nextFail)}else{nextSuccess(res)}}}if(fail){constonReject=function(val){if(typeoffail!=="function"){nextSuccess(val)}else{constres=fail(val)if(resinstanceofSimplePromise){res.then(nextSuccess,nextFail)}else{nextSuccess(res)}}}}else{onReject=function(){}}switch(this._status){案例“待定”:this._onSuccess.push(onFullfil)this._onFail.push(onReject)中断;案例“已解决”:onFullfil(this._value)中断;案例“REJECTED”:onReject(this._value)break;}})}}对于传入then方法的参数,先判断是否是函数,判断为否,直接执行下一个then的成功函数;如果判断为是,则判断该函数的返回值res类型是否为Promise,如果不是,则直接执行下一个then的成功函数,如果是,则通过then调用下一个函数所以,上面的问题不是很难得到答案。doSomething().then(function(){returndoSomethingElse();//返回值为Promise}).then(finalHandler);RETURN:doSomething--->doSomethingElse(undefined)--->final(doSomethingElseResult)doSomething().then(function(){doSomethingElse();//返回值未定义}).then(finalHandler);RETURN:doSomething--->doSomethingElse(undefined)--->final(undefined)doSomething().then(doSomethingElse())//参数typeof!=function.then(finalHandler);RETURN:doSomethingdoSomethingElse(undefined)-->final(doSomethingResult)doSomething().then(doSomethingElse)//调用方式不同于1.then(finalHandler);RETURN:doSomething--->doSomethingElse(doSomethingResult)--->final(doSomethingElseResult)好了,then方法就完善了。静态函数接下来是Promise类的各种静态函数SimplePromise(){...staticall(){}staticrace(){}staticresolve(){}staticreject(){}}allstaticall(promiselist){if(Array.isArray(promiselist)){constlen=promiselist.length;constcount=0constarr=[]returnnewSimplePromise((res,rej)=>{for(leti=0;i
