手寫 Promise
Promise 的用法 :
let?p?=?new?Promise(function(resolve,?reject){
????console.log(111)
????setTimeout(function(){
????????resolve(2)
????},?1000)
})
p.then(function(res){
????console.log('suc',res)
},function(err){
????console.log('err',err)
})
可以看到new了一個Promise,里面有一個回調(diào)函數(shù),回調(diào)函數(shù)里有2個參數(shù),分別又是另外2個函數(shù)。其實里面很多也都是回調(diào)函數(shù)的封裝調(diào)用。
const?[PENDING,RESOLVED,REJECTED]=["PENDING","RESOLVED","REJECTED"];`
class?Promise1?{
????
????constructor(executor){
????????state?=?PENDING;
????????value?=?undefined;
????????reason?=?undefined;
????????
????????resolve?=?(value)?=>?{
????????????if(this.state?===?PENDING){
????????????????this.state?=?RESOLVED;
????????????????this.value?=?value;
????????????}
????????}
????????reject?=?(reason)?=>?{
????????????if(this.state?===?PENDING){
????????????????this.state?=?REJECTED;
????????????????this.value?=?reason;
????????????}
????????}
????????
????????try{
????????????executor(this.resolve,this.reject)
????????}catch(e){
????????????reject(e)
????????}
????}
?}
測試一下執(zhí)行情況:
let?p1?=?new?Promise1((resolve,reject)=>{//function:executor
????console.log(111)
????setTimeout(()=>{
????????resolve(111)//this.resolve,直接傳參調(diào)用
????},?1000)
})
下面就是 then 了
class?Promise1?{
????constructor(executor){
????????...
????????onResolvedCallbacks=[];?//then,pending里先存起來
????????onRejectedCallbacks=[];
????????...
????????resolve?=?(value)?=>?{
????????????if(this.state?===?PENDING){
????????????????...
????????????????//executor里如果是異步會把then里存起來,然后executor走完了resolved的話,會再調(diào)then里回調(diào)函數(shù)
????????????????this.onResolvedCallbacks.forEach(fn?=>?fn(value))
????????????}
????????}
????????reject?=?(reason)?=>?{
????????????if(this.state?===?PENDING){
????????????????...
???????????????this.onRejectedCallbacks.forEach(fn?=>?fn(reason))
????????????}
????????}
????}
????
????then(onResolved,onRejected){
????????onResolved?=?typeof?onResolved?===?'function'???onResolved?:?value?=>?value;
????????onRejected?=?typeof?onRejected?===?'function'???onRejected?:?reason?=>?{
????????????throw?reason
????????};
????????
????????switch(this.state){
????????????case?RESOLVED?:?//狀態(tài)變了,就直接把結(jié)果給出去
????????????????onResolved(this.value);
????????????case?REJECTED?:
????????????????onRejected(this.reason);
????????????case?PENDING?:?
????????????//如果是pending的話,說明executor還沒走完,先存起來,走完再調(diào)用
????????????????this.onResolvedCallbacks.push(onResolved);
????????????????this.onRejectedCallbacks.push(onRejected)
????????}
????}
}
測試一下 :
let?p2?=?new?Promise1((resolve,?reject)?=>?{
????setTimeout(()=>{
????????resolve(222)
????},?1000)
})
p2.then(res?=>?console.log(res,?'res'))?//222
鏈?zhǔn)秸{(diào)用:
class?Promise1?{
????...
????
????
????then(onResolved,onRejected){
????????...
????????//返回一個promise1
????????let?newPromise=new?Promise1((resolve,reject)=>{
????????????switch(this.state){
????????????????case?RESOLVED?:?//狀態(tài)變了,就直接把結(jié)果給出去
????????????????????setTimeout(()=>{//then,放后面處理
????????????????????????try{
????????????????????????let?reValue=onResolved(this.value);
?rePromise(newPromise,reValue,resolve,reject)
????????????????????????}catch(e){reject(e)}
????????????????????},0)
????????????????????
????????????????case?REJECTED?:
????????????????????setTimeout(()=>{
????????????????????????try{
????????????????????????????let?reValue=onRejected(this.reason);
????????????????????????????rePromise(newPromise,reValue,resolve,reject)
????????????????????????}catch(e){reject(e)}
????????????????????},0)
????????????????????
????????????????case?PENDING?:?
????????????????//如果是pending的話,說明executor還沒走完,先存起來,走完再調(diào)用
????????????????????this.onResolvedCallbacks.push(()=>{
????????????????????????setTimeout(()=>{
????????????????????????????try{
????????????????????????????????let?reValue=onResolved(this.value);
?rePromise(newPromise,reValue,resolve,reject)
????????????????????????????}catch(e){reject(e)}
????????????????????????},0)
????????????????????});
????????????????????this.onRejectedCallbacks.push(()=>{
????????????????????????setTimeout(()=>{
????????????????????????????try{
????????????????????????????????let?reValue=onRejected(this.reason);
????????????????????????????rePromise(newPromise,reValue,resolve,reject)
????????????????????????????}catch(e){reject(e)}
????????????????????????},0)
????????????????????})
????????????}
????????})
????????return?newPromise;
????}
}
//newPromise:新的promise1對象,reValue:上一個then的返回值,newPromise.resolve,newPromise.reject
function?rePromise(newPromise,reValue,resolve,reject){
????//相當(dāng)于把自己return出去了,let?p2?=?p.then(res?=>?p2);
????if(newPromise?===?reValue){
????????reject(new?TypeError('循環(huán)了'))
????}
????if(reValue?!==?null?&&?(typeof?reValue?===?'object'?||?typeof?reValue?===?'function')){
????????try{
????//判斷一下reValue是不是promise1,是個對象,還帶有then函數(shù)
????//如果有then并是個函數(shù),就調(diào)then;?
????????????let?then?=?reValue.then;
????????????if(typeof?then?===?'function'){
????????????????then.call(reValue,?res=>{
????????????????????resolve(res)
????????????????},err=>{
????????????????????reject(err)
????????????????})
????????????}else{//then不是函數(shù),直接用resolve返回值
????????????????resolve(reValue)
????????????}
????????}catch(e){
????????????reject(e)
????????}
????}else{//只是個普通值
????????resolve(reValue)
????}
}
測試一下:
p3.then(res?=>?{
????console.log(res)
????return?new?Promise1((resolve,?reject)?=>?{
????????resolve('p3')
????})
}).then(res?=>?console.log(res,?'pp3'))//p3
但還有個問題
...
function?rePromise(newPromise,reValue,resolve,reject){
????...
????let?called;//是否調(diào)用過,防止多次調(diào)用
????if(reValue?!==?null?&&?(typeof?reValue?===?'object'?||?typeof?reValue?===?'function')){
????????try{
???
????????????let?then?=?reValue.then;
????????????if(typeof?then?===?'function'){
????????????????then.call(reValue,?res=>{
????????????????????if(called)?return;
????????????????????called?=?true;
???????????????????//promise1就繼續(xù)下一個,直到then走完,變成普通的值?
???????????????????rePromise(newPromise,res,resolve,reject)
????????????????},err=>{
????????????????????if(called)?return;
????????????????????called?=?true;
????????????????????reject(err)
????????????????})
????????????}else{//then不是函數(shù),直接用resolve返回值
????????????????resolve(reValue)
????????????}
????????}catch(e){
????????????if(called)?return;
????????????called?=?true;
????????????reject(e)
????????}
????}else{//只是個普通值
????????resolve(reValue)
????}
}
測試一下
let?p1=new?Promise1((resolve,reject)=>{
????????resolve(111)
????})
????let?p2=p1.then(res=>{console.log(res,'p1')},err=>console.log(err,'p1'));
????p2.then(res=>console.log(res,'p2'))
????.then(res=>console.log(res,'p3))
還有其它屬性:
class?Promise1?{
????...
????catch(onReject){
????????return?this.then(null,onReject)
????}
????defer(){
????????let?defer={};
????????defer.promise=new?Promise1((resolve,reject)=>{
????????????defer.resolve=resolve;
????????????defer.reject=reject;
????????})
????????return?defer;
????}
????deffered(){
????????return?this.defer;
????}
????all(promises){
????????return?new?Promise1((resolve,reject)=>{
????????????let?done=gen(promises.length,resolve);
????????????for(let?i=0;i????????????????promises[i].then(res=>{
????????????????????done(i,res)
????????????????},reject)
????????????}
????????})
????}

評論
圖片
表情
