自定义Promise

    科技2022-08-26  101

    一,整体结构

    采用es5的语法来写:

    //es5里面自定义模块,用的是IIFE(函数自调用) (function(window){ //定义promise构造函数 //参数是excutor函数:同步执行 function Promise(excutor){ } // Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象 Promise.prototype.then=function (onResolved,onRejected){ } // Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象 Promise.prototype.catch=function (onRejected){ } //Promise函数对象的方法:resolve,返回一个成功值为value的promise对象 Promise.resolve=function(value){ } //Promise函数对象的方法:reject,返回一个失败值为reason的promise对象 Promise.reject=function(reason){ } //Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时) Promise.all=function(promises){ } //Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的) Promise.race=function(promises){ } //向外暴露这个Promise函数,绑定为window的属性 window.Promise=Promise })(window)

    二,构造函数Promise的实现

    第一步:因为excutor是立即同步执行的,所以在promise函数内部需要调用这个excutor函数,并且参数是resolve和reject这两个回调函数。 第二步:因为参数是这两个回调函数,所以这两个回调函数就需要事先定义好。 第三步:根据平时对promise的使用,可以知道,promise必然有个状态属性(peding,resolve,reject),还有一个用于存储结果的属性,还有一个存储回调函数的数组:

    //es5里面自定义模块,用的是IIFE(函数自调用) (function(window){ //定义promise构造函数 //参数是excutor函数:同步执行 function Promise(excutor){ //因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下 const that=this that.status='pending' //给promise对象指定状态属性,初始值为pending that.data=undefined //给promise对象指定一个用于存储结果数据的属性 that.callbacks=[] //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} } function resolve(value){ //如果状态不是pending,直接结束 if(that.status!=='pending'){return} //将状态改为resolved that.status='resolved' //保存value数据 that.data=value //如果有待执行的callback函数,立即异步执行回调函数onResolved if(that.callbacks.length>0){ setTimeout(()=>{//让他异步执行,所有成功的回调 that.callbacks.forEach(callbacksObj=>{ callbacksObj.onResolved(value) }) }) } } function reject(reason){ //如果状态不是pending,直接结束 if(that.status!=='pending'){return} //将状态改为rejected that.status='rejected' //保存reason数据 that.data=reason //如果有待执行的callback函数,立即异步执行回调函数onRejected if(that.callbacks.length>0){ setTimeout(()=>{//让他异步执行,所有成功的回调 that.callbacks.forEach(callbacksObj=>{ callbacksObj.onRejected(reason) }) }) } } //需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数 try{ excutor(resolve,reject) }catch(error){ //如果执行器抛出异常,promise对象变为rejected状态 reject(error) } } // Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象 Promise.prototype.then=function (onResolved,onRejected){ //假设当前状态还是pending状态,将回调函数保存起来 this.callbacks.push({ onResolved, onRejected }) } // Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象 Promise.prototype.catch=function (onRejected){ } //Promise函数对象的方法:resolve,返回一个成功值为value的promise对象 Promise.resolve=function(value){ } //Promise函数对象的方法:reject,返回一个失败值为reason的promise对象 Promise.reject=function(reason){ } //Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时) Promise.all=function(promises){ } //Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的) Promise.race=function(promises){ } //向外暴露这个Promise函数,绑定为window的属性 window.Promise=Promise })(window)

    也就是说:这部分是excutor实参, 而在promise构造函数内部,第一个执行的就是这个实参函数: 而这里面调用了resolve(1),这个1类比于异步操作的结果 于是就去执行resolve函数,也就是说resolve是定义者定义在promise中,使用者在外面异步操作完成后调用。 而resolve里还要调用.then中的函数: 简单写: 这样就是先指定两个回调函数,等resolve调用时,就可以直接在callbacks里面找到并使用了。

    三,then方法的实现

    //es5里面自定义模块,用的是IIFE(函数自调用) (function(window){ const PENDING='pending' const RESOLVED='resolved' const REJECTED='rejected' //定义promise构造函数 //参数是excutor函数:同步执行 function Promise(excutor){ //因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下 const that=this that.status=PENDING //给promise对象指定状态属性,初始值为pending that.data=undefined //给promise对象指定一个用于存储结果数据的属性 that.callbacks=[] //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} } function resolve(value){ //如果状态不是pending,直接结束 if(that.status!==PENDING){return} //将状态改为resolved that.status=RESOLVED //保存value数据 that.data=value //如果有待执行的callback函数,立即异步执行回调函数onResolved if(that.callbacks.length>0){ setTimeout(()=>{//让他异步执行,所有成功的回调 that.callbacks.forEach(callbacksObj=>{ callbacksObj.onResolved(value) }) }) } } function reject(reason){ //如果状态不是pending,直接结束 if(that.status!==PENDING){return} //将状态改为rejected that.status=REJECTED //保存reason数据 that.data=reason //如果有待执行的callback函数,立即异步执行回调函数onRejected if(that.callbacks.length>0){ setTimeout(()=>{//让他异步执行,所有成功的回调 that.callbacks.forEach(callbacksObj=>{ callbacksObj.onRejected(reason) }) }) } } //需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数 try{ excutor(resolve,reject) }catch(error){ //如果执行器抛出异常,promise对象变为rejected状态 reject(error) } } // Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象 Promise.prototype.then=function (onResolved,onRejected){ //默认的成功回调函数 onResolved=typeof onResolved === 'function' ? onResolved : value=>value //指定默认的失败的回调(实现错误/异常传透的关键点) onRejected=typeof onRejected === 'function' ? onRejected : reason=>{throw reason} const that=this //返回一个新的promise对象,里面的参数依旧是excutor函数 return new Promise((resolve,reject)=>{ //调用指定的回调函数来处理那三种返回值的情况 // 1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常 // 2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。 // 3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果 function handle(callback){ try{ const result =callback(that.data) if(result instanceof Promise){ //判断返回是promise的实例对象 result.then( value=>resolve(value), //当result成功时,让return的promise也成功 reason=>reject(reason) //当result失败时,让return的promise也失败 ) }else{ //返回是非promise的任意值,新promise变为resolved,value为返回的值。 resolve(result) } }catch(error){ //这里写得是then的回调函数里面,抛出异常了,新promise变为rejected状态,reason为抛出的异常 reject(error) } } if(that.status===PENDING){ //假设当前状态还是pending状态,此时是先指定回调函数,后改变状态。将回调函数保存起来 //因为需要改状态,所以这样写,而不是直接handle(onResolved) this.callbacks.push({ onResolved(value){ handle(onResolved) }, onRejected(reason){ handle(onRejected) } }) }else if(that.status===RESOLVED){ //现在已经成功了,必然已经执行了resolve函数,所以结果必然存储在this.status里面 setTimeout(()=>{ handle(onResolved) }) }else{ //现在已经失败,必然已经执行了reject函数,所以结果必然存储在this.status里面 setTimeout(()=>{ handle(onRejected) }) } }) } // Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象 Promise.prototype.catch=function (onRejected){ return this.then(undefined,onRejected) } //Promise函数对象的方法:resolve,返回一个成功值为value的promise对象 Promise.resolve=function(value){ } //Promise函数对象的方法:reject,返回一个失败值为reason的promise对象 Promise.reject=function(reason){ } //Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时) Promise.all=function(promises){ } //Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的) Promise.race=function(promises){ } //向外暴露这个Promise函数,绑定为window的属性 window.Promise=Promise })(window)

    四,Promise.resolve和reject的实现

    //Promise函数对象的方法:resolve,返回一个成功值为value的promise对象 Promise.resolve=function(value){ //返回一个promise成功/失败 return new Promise((resolve,reject)=>{ //value是一个promise时 if(value instanceof Promise){//根据value的结果作为pormise的结果 value.then( value=>resolve(value), //当result成功时,让return的promise也成功 reason=>reject(reason) //当result失败时,让return的promise也失败 ) }else{ //value不是一个promise=>promise变为成功,数据是value resolve(value) } }) } //Promise函数对象的方法:reject,返回一个失败值为reason的promise对象 Promise.reject=function(reason){ //返回一个失败的promise return new Promise((resolve,reject)=>{ reject(reason) }) }

    五,Promise.all方法

    //Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时) Promise.all=function(promises){ const values =new Array(promises.length) let acount=0 return new Promise((resolve,reject)=>{ //遍历获取每一个promises内部的promise promises.forEach((p,index)=>{ p.then( value=>{ //p成功,将成功的value保存到values里,且要按顺序 values[index]=value //如果全部成功了,就将return的promise改变为成功 acount++ if(acount===promises.length){ resolve(values) } }, reason=>{ //只要一个失败了,return的promise函数就失败 reject(reason) } ) }) }) }

    六,Promise.race方法

    //Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的) Promise.race=function(promises){ return new Promise((resolve,reject)=>{ //遍历获取每一个promises内部的promise promises.forEach((p,index)=>{ p.then( value=>{//一旦有成功的,把return变为成功promise resolve(value) }, reason=>{ //一旦有失败的,把return变为失败promise reject(reason) } ) }) })

    七,整体的promise

    //es5里面自定义模块,用的是IIFE(函数自调用) (function(window){ const PENDING='pending' const RESOLVED='resolved' const REJECTED='rejected' //定义promise构造函数 //参数是excutor函数:同步执行 function Promise(excutor){ //因为后面resolve和reject是程序员使用者直接在外面调用,this会变成window,故这里保存一下 const that=this that.status=PENDING //给promise对象指定状态属性,初始值为pending that.data=undefined //给promise对象指定一个用于存储结果数据的属性 that.callbacks=[] //放回调函数的,每个元素的结构:{ onResolved(){},onRejected(){} } function resolve(value){ //如果状态不是pending,直接结束 if(that.status!==PENDING){return} //将状态改为resolved that.status=RESOLVED //保存value数据 that.data=value //如果有待执行的callback函数,立即异步执行回调函数onResolved if(that.callbacks.length>0){ setTimeout(()=>{//让他异步执行,所有成功的回调 that.callbacks.forEach(callbacksObj=>{ callbacksObj.onResolved(value) }) }) } } function reject(reason){ //如果状态不是pending,直接结束 if(that.status!==PENDING){return} //将状态改为rejected that.status=REJECTED //保存reason数据 that.data=reason //如果有待执行的callback函数,立即异步执行回调函数onRejected if(that.callbacks.length>0){ setTimeout(()=>{//让他异步执行,所有成功的回调 that.callbacks.forEach(callbacksObj=>{ callbacksObj.onRejected(reason) }) }) } } //需要立即同步执行excutor函数,但他需要两个回调函数作为参数,故在这之前需要先定义好这两个回调函数 try{ excutor(resolve,reject) }catch(error){ //如果执行器抛出异常,promise对象变为rejected状态 reject(error) } } // Promise原型对象的then方法,两个参数是回调函数(成功和失败),返回一个新的promise对象 Promise.prototype.then=function (onResolved,onRejected){ //默认的成功回调函数 onResolved=typeof onResolved === 'function' ? onResolved : value=>value //指定默认的失败的回调(实现错误/异常传透的关键点) onRejected=typeof onRejected === 'function' ? onRejected : reason=>{throw reason} const that=this //返回一个新的promise对象,里面的参数依旧是excutor函数 return new Promise((resolve,reject)=>{ //调用指定的回调函数来处理那三种返回值的情况 // 1,如果抛出异常,新promise变为rejected状态,reason为抛出的异常 // 2,如果返回的是非promise的任意值,新promise变为resolved,value为返回的值。 // 3,如果返回的是另一个新的promise,此promise的结果就会变成新promise的结果 function handle(callback){ try{ const result =callback(that.data) if(result instanceof Promise){ //判断返回是promise的实例对象 result.then( value=>resolve(value), //当result成功时,让return的promise也成功 reason=>reject(reason) //当result失败时,让return的promise也失败 ) }else{ //返回是非promise的任意值,新promise变为resolved,value为返回的值。 resolve(result) } }catch(error){ //这里写得是then的回调函数里面,抛出异常了,新promise变为rejected状态,reason为抛出的异常 reject(error) } } if(that.status===PENDING){ //假设当前状态还是pending状态,此时是先指定回调函数,后改变状态。将回调函数保存起来 //因为需要改状态,所以这样写,而不是直接handle(onResolved) this.callbacks.push({ onResolved(value){ handle(onResolved) }, onRejected(reason){ handle(onRejected) } }) }else if(that.status===RESOLVED){ //现在已经成功了,必然已经执行了resolve函数,所以结果必然存储在this.status里面 setTimeout(()=>{ handle(onResolved) }) }else{ //现在已经失败,必然已经执行了reject函数,所以结果必然存储在this.status里面 setTimeout(()=>{ handle(onRejected) }) } }) } // Promise原型对象的catch方法,一个参数是回调函数(失败),返回一个新的promise对象 Promise.prototype.catch=function (onRejected){ return this.then(undefined,onRejected) } //Promise函数对象的方法:resolve,返回一个成功值为value的promise对象 Promise.resolve=function(value){ //返回一个promise成功/失败 return new Promise((resolve,reject)=>{ //value是一个promise时 if(value instanceof Promise){//根据value的结果作为pormise的结果 value.then( value=>resolve(value), //当result成功时,让return的promise也成功 reason=>reject(reason) //当result失败时,让return的promise也失败 ) }else{ //value不是一个promise=>promise变为成功,数据是value resolve(value) } }) } //Promise函数对象的方法:reject,返回一个失败值为reason的promise对象 Promise.reject=function(reason){ //返回一个失败的promise return new Promise((resolve,reject)=>{ reject(reason) }) } //Promise函数对象的方法:all(接收参数为promise的数组),返回promise对象构成数组(都成功时) Promise.all=function(promises){ const values =new Array(promises.length) let acount=0 return new Promise((resolve,reject)=>{ //遍历获取每一个promises内部的promise promises.forEach((p,index)=>{ p.then( value=>{ //p成功,将成功的value保存到values里,且要按顺序 values[index]=value //如果全部成功了,就将return的promise改变为成功 acount++ if(acount===promises.length){ resolve(values) } }, reason=>{ //只要一个失败了,return的promise函数就失败 reject(reason) } ) }) }) } //Promise函数对象的方法:race(接收参数为promise的数组),返回promise对象(第一个完成的) Promise.race=function(promises){ return new Promise((resolve,reject)=>{ //遍历获取每一个promises内部的promise promises.forEach((p,index)=>{ p.then( value=>{//一旦有成功的,把return变为成功promise resolve(value) }, reason=>{ //一旦有失败的,把return变为失败promise reject(reason) } ) }) }) } //向外暴露这个Promise函数,绑定为window的属性 window.Promise=Promise })(window)
    Processed: 0.028, SQL: 9