手写一个自己的promise

299 阅读15分钟

一、前言

经过前面promise的基础学习,已经知道了promise的基本用法。但为了能在用promise的时候遇到问题时,能够精准定位问题和解决问题,需要对promise有个更深层次的认识。所以我们可以去手写个自己的pormise来增加对promise的理解。

我们知道,promise有三种状态pending(进行中)、fulfilled(已成功)和rejected(已失败)。

promise被调用后最先是处于pending状态的,只有手动调用promise构造函数中回调方法的resolve或reject才能够改变promise的状态,否则这个promise将一直处于pending状态。

二、定义初始结构

明白了这个,我们就可以开始写自己的promise了。我们平时用promise时是要通过new来创建实例的:

const promise = new Promise(() => {});

那我们的promise可以用class来进行定义

//自己手写的promise
class MyPromise {}

然后我们知道,我们在用promise的时候要给promise传一个构造函数,并且这个构造函数要传两个参数,一般叫resolve和reject。可以通过这两个参数来决定promise的最终状态。

const promise = new Promise((resolve,reject) => {});

所以我们的promise要有一个构造器去接收这个构造函数和参数,我们可以这样写:

//自己手写的promise
class MyPromise {
    constructor(executor) {
    	executor(resolve,reject);
  }
}

三、实现resolve和reject方法

但是这样写有一个明显的问题是,构造器中的resolve和reject我们没有进行定义,如果在我们手写的promise中执行resolve()或reject()不知道执行哪里的resolve和reject,所以我们得在我们手写的promise中加多两个方法。别忘了,在class中我们是需要用this来调用自身的方法的,所以我们在构造器中加上this关键字。

//自己手写的promise
class MyPromise {
    constructor(executor) {
    	executor(this.resolve,this.reject);
  }
   resolve(){}
   reject(){}
}
1、管理状态

然后就是promise有三种状态,初始化的promise是处于pending状态的,pending状态可以转为fulfilled和rejected状态。而且promise的状态的一但被改变就不可在更改,所以我们可以用一个变量来保存promise的状态。代码可以这样写。

//自己手写的promise
class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
    	executor(this.resolve,this.reject);
  }
   resolve(){}
   reject(){}
}

当执行resolve()或reject()的时候promise的状态就从pending转为fulfilled或rejected,且状态只能改变一次。所以我们可以通过判断promise此时的状态是否为pending来决定promise的状态是否能进行改变。

class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
    	executor(this.resolve,this.reject);
  }
   resolve(){
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseState = MyPromise.FULFILLED;
   }
   reject(){
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseState = MyPromise.REJECTED;
   }
}
2、保存值

在我们平时用promise的时候,在调用resolve和reject的时候是可以传参的,那我们的resolve和reject方法需要接收传过来的参数,并且把他保存到promise实例中,这样能保证每一个promise都有一个最终的值。

class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
    	executor(this.resolve,this.reject);
  }
   resolve(value){
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = value;
       this.promiseState = MyPromise.FULFILLED;
   }
   reject(reason){
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = reason;
       this.promiseState = MyPromise.REJECTED;
   }
}
3、this指向问题

但是这样写会有问题,当我们执行如下代码的时候

const promise = new MyPromise((resolve,reject) => {
    resolve();
});

会出现一个错误

Snipaste_2022-02-24_10-49-17.jpg

为什么会出现这个错误呢?在class中的this默认指向类的实例。但是如果将某个方法单独拿出来调用,此时的this就是Undefined,因为class内部是默认严格模式,不会指向window对象。一般解决这个问题可以通过箭头函数或者bind和proxy进行解决,在这里我就用箭头函数。所以我们的代码变成了下面这个样子。

class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
    	executor(this.resolve,this.reject);
  }
   resolve = (value) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = value;
       this.promiseState = MyPromise.FULFILLED;
   }
   reject = (reason) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = reason;
       this.promiseState = MyPromise.REJECTED;
   }
}

四、实现then方法

1、状态不可变

接下来再来看看then方法,在then方法中我们可以传两个回调函数,第一个是处理成功状态的回调,第二个是处理拒绝状态的回调。promise的状态从上面的代码中我们可以知道,当调用了resolve()状态变为成功状态,调用了reject()状态变为拒绝状态,且这种状态的改变只能发生一次。所以执行then方法的时候,此时的promise的状态是已经知道的了。所以代码可以这么写。

class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
    	executor(this.resolve,this.reject);
  }
   resolve = (value) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = value;
       this.promiseState = MyPromise.FULFILLED;
   }
   reject = (reason) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = reason;
       this.promiseState = MyPromise.REJECTED;
   }
+   then = (onfulfilled,onrejected) => {
+       //如果是成功状态,执行第一个回调函数
+       if(this.promiseState === MyPromise.FULFILLED){
+           onfulfilled(this.promiseValue);
+       }
+       //如果是失败状态,执行第二个回调函数
+       if(this.promiseState === MyPromise.REJECTED){
+           onrejected(this.promiseValue);
+       }
   }
}

//测试代码
const promise = new MyPromise((resolve,reject) => {
    resolve('成功状态');
    reject('失败状态');
});
promise.then(
    resolve => {
        console.log(resolve);
    },
    reject => {
        console.log(reject);
    }
);

执行上面的测试代码,我们查看下控制台

Snipaste_2022-02-24_14-26-40.jpg

成功状态被输出,失败状态没有输出,说明我们此时的promise是正确的。

2、异常捕获

但是如果我们的测试代码变成下面这个样子

const promise = new MyPromise((resolve,reject) => {
   throw new Error('出错了');
});

虽然这里有错误并且将其抛了出去,在我们自己手写的promise中,我们并没有对这里的错误进行处理。所以最终显示结果会如下所示,未捕获异常

Uncaught 未捕获

我们可以在执行resolve()和reject()之前用try/catch进行判断,在构造函数 constructor里面完善代码,判断生成实例的时候是否有报错

  • 如果没有报错的话,就按照正常执行resolve()和reject()方法
  • 如果报错的话,就把错误信息传入给reject()方法,并且直接执行reject()方法
class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
 +   	try {
 +       	executor(this.resolve,this.reject);
 +   	} catch (error) {
 +       	this.reject(error);
 +   	}
  }
   resolve = (value) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = value;
       this.promiseState = MyPromise.FULFILLED;
   }
   reject = (reason) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = reason;
       this.promiseState = MyPromise.REJECTED;
   }
   then = (onfulfilled,onrejected) => {
       //如果是成功状态,执行第一个回调函数
       if(this.promiseState === MyPromise.FULFILLED){
           onfulfilled(this.promiseValue);
       }
       //如果是失败状态,执行第二个回调函数
       if(this.promiseState === MyPromise.REJECTED){
           onrejected(this.promiseValue);
       }
   }
}
3、then方法传参问题

在原生Promise里then方法里面的两个参数如果不是函数的话也是能够正常运行的。我们在原生代码这里不传入函数作为参数而是传入null,具体例子如下:

const promise = new Promise((resolve,reject) => {
    resolve('成功');
});
promise.then(
    null,
    reject => {
        console.log(reject);
    }
);

我们发现他是可以正常执行的。

但是如果在我们自己手写的promise中,不传入函数作为参数:

const promise = new MyPromise((resolve,reject) => {
    resolve('成功');
});
promise.then(
    null,
    reject => {
        console.log(reject);
    }
);

我们发现他在控制台中会报 Uncaught TypeError: onfulfilled is not a function的错误。说onfulfilled不是一个function

这显然不是我们想要的,我们可以判断传过来的参数是否为函数,如果不是函数我们就把他包装成一个函数就可以了。我们的代码可以这样子写:

class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
    	try {
        	executor(this.resolve,this.reject);
    	} catch (error) {
        	this.reject(error);
    	}
  }
   resolve = (value) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = value;
       this.promiseState = MyPromise.FULFILLED;
   }
   reject = (reason) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = reason;
       this.promiseState = MyPromise.REJECTED;
   }
   then = (onfulfilled,onrejected) => {
+       //如果onfulfilled不是函数,将其封装成一个函数
+      if(typeof onfulfilled !== 'function') onfulfilled = () => {};
       
+       //如果onrejected不是函数,抛出一个错误
+    	if(typeof onfulfilled !== 'function') onrejected = () => {throw Error(this.promiseValue)};
       
       //如果是成功状态,执行第一个回调函数
       if(this.promiseState === MyPromise.FULFILLED){
           onfulfilled(this.promiseValue);
       }
       //如果是失败状态,执行第二个回调函数
       if(this.promiseState === MyPromise.REJECTED){
           onrejected(this.promiseValue);
       }
   }
}

五、实现异步

1、出现的问题

经过这样的修改,我们的then方法就基本大功告成了,但我们手写得promise还是有一些问题的,比如用原生的promise执行下面的例子:

console.log(1);
const promise = new Promise((resolve,reject) => {
    console.log(2);
    resolve('resolve');
});
promise.then(
    resolve => {
        console.log(resolve);
    }
);
console.log(3);

输出顺序为

1
2
3
resolve

但是如果用我们自己写的promise去执行这段代码,输出顺序就会变为

1
2
resolve
3
2、用setTimeout解决问题

两者输出的顺序不对,原因其实很简单,因为promise中then方法里面的代码是属于微任务,也就是console.log(resolve);这段代码是微任务,其他的都是属于同步任务,在一个宏任务中,是先执行完所有的同步任务后再去执行微任务的。而我们自己写的promise没有去设置微任务,所以导致输出顺序不同。在这里我们用setTimeout来代替微任务。我们可以在then函数中进行设置。

class MyPromise {
    ...
   then = (onfulfilled,onrejected) => {
       //如果onfulfilled不是函数,将其封装成一个函数
      if(typeof onfulfilled !== 'function') onfulfilled = () => {};
       
       //如果onrejected不是函数,抛出一个错误
    	if(typeof onfulfilled !== 'function') onrejected = () => {throw Error(this.promiseValue)};
       
       //如果是成功状态,执行第一个回调函数
       if(this.promiseState === MyPromise.FULFILLED){
 +         setTimeout(() => {
               onfulfilled(this.promiseValue);
 +         })
       }
       //如果是失败状态,执行第二个回调函数
       if(this.promiseState === MyPromise.REJECTED){
 +          setTimeout(() => {
               onrejected(this.promiseValue);
 +        })
       }
   }
}

将代码改成这样子再去执行上面的测试例子,我们就发现输出顺序就跟原生的promise的输出顺序是一样的了。

3、回调保存

这样看来我们的then方法似乎差不多了,但是还是有问题的,我们看下面原生的promise的测试例子。

const promise = new Promise((resolve,reject) => {
     setTimeout(() => {
        resolve('测试例子');
    },1000)
    
});
promise.then(
    resolve => {
        console.log(resolve);
    }
);

我们发现在控制台中测试例子会在一秒后成功输出,但是如果把原生的promise换成我们自己写的promise就会发现在控制台中不会输出测试例子。这是为什么呢?这是因为我们设置了setTimeout,当执行到then方法的时候,此时的promise还没有去执行**resolve('测试例子')**去改变promise的状态,此时的promise依然是pending状态的,所以在我们写的then方法中既没有去执行成功状态的回调也没有去执行拒绝状态的回调。

因为此时的promise的状态还没有进行改变,我们需要等promise的状态改变后再去执行then里面的函数,等resolve执行了以后,再执行then

为了保留then里的函数,我们可以创建 数组保存函数

为什么用 数组 来保存这些回调呢?因为一个promise实例可能会多次 then,也就是经典的 链式调用,而且数组是先入先出的顺序

在实例化promise的时候,我们就可以创建个数组:

  • promiseCallbacks:用来保存回调
class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
+	promiseCallbacks = [];//用来保存回调
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
    	try {
        	executor(this.resolve,this.reject);
    	} catch (error) {
        	this.reject(error);
    	}
  }
}

接下来我们就是改善下then方法

class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
	promiseCallbacks = [];//用来保存回调
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
    	try {
        	executor(this.resolve,this.reject);
    	} catch (error) {
        	this.reject(error);
    	}
     }
   then = (onfulfilled,onrejected) => {
       //如果onfulfilled不是函数,将其封装成一个函数
      if(typeof onfulfilled !== 'function') onfulfilled = () => {};
       
       //如果onrejected不是函数,抛出一个错误
    	if(typeof onfulfilled !== 'function') onrejected = () => {throw Error(this.promiseValue)};
       
        //如果是pending状态的,将回调函数保存在数组中
 +       if(this.promiseState === MyPromise.PENDING) {
 +           this.promiseCallbacks.push({onfulfilled,onrejected});
 +       }
        
       //如果是成功状态,执行第一个回调函数
       if(this.promiseState === MyPromise.FULFILLED){
          setTimeout(() => {
               onfulfilled(this.promiseValue);
          })
       }
       //如果是失败状态,执行第二个回调函数
       if(this.promiseState === MyPromise.REJECTED){
           setTimeout(() => {
               onrejected(this.promiseValue);
         })
       }
   }
}

接下来我们要完善下resolvereject方法了,在执行resolvereject方法时判断promiseCallbacks里有没有值,如果有值遍历执行

class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
	promiseCallbacks = [];//用来保存回调
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
    	try {
        	executor(this.resolve,this.reject);
    	} catch (error) {
        	this.reject(error);
    	}
     }
   resolve = (value) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = value;
       this.promiseState = MyPromise.FULFILLED;
 +      this.promiseCallbacks.forEach(callback => {
 +          callback.onfulfilled(value)
 +      });
   }
   reject = (reason) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       this.promiseValue = reason;
       this.promiseState = MyPromise.REJECTED;
 +      this.promiseCallbacks.forEach(callback => {
 +          callback.onrejected(reason)
 +      });
   }
   then = (onfulfilled,onrejected) => {
       //如果onfulfilled不是函数,将其封装成一个函数
      if(typeof onfulfilled !== 'function') onfulfilled = () => {};
       
       //如果onrejected不是函数,抛出一个错误
    	if(typeof onfulfilled !== 'function') onrejected = () => {throw Error(this.promiseValue)};
       
        //如果是pending状态的,将回调函数保存在数组中
        if(this.promiseState === MyPromise.PENDING) {
            this.promiseCallbacks.push({onfulfilled,onrejected});
        }
        
       //如果是成功状态,执行第一个回调函数
       if(this.promiseState === MyPromise.FULFILLED){
          setTimeout(() => {
               onfulfilled(this.promiseValue);
          })
       }
       //如果是失败状态,执行第二个回调函数
       if(this.promiseState === MyPromise.REJECTED){
           setTimeout(() => {
               onrejected(this.promiseValue);
         })
       }
   }
}

完善之后,我们在执行上面的例子,就发现测试例子在一秒后成功输出了,证明我们的代码没有问题

还有一个细节问题我们是需要知道的,比如执行下面的例子。

const promise = new Promise((resolve,reject) => {
     setTimeout(() => {
        resolve('测试例子');
        console.log(4444);
    },1000)
});
promise.then(
    resolve => {
        console.log(resolve);
    }
);

在原生的Promise中是先输入4444在输出测试例子,而在我们自己写的promise中确实反过来的。这是什么原因呢?之前也分析过这个原因,因为then方法里面的代码是异步中的微任务,而console.log(4444)这段代码是同步任务来的,同步任务要优先异步任务执行。所以为了实现这个,我们在resolve和reject方法中加setTimeout就可以了。

class MyPromise {
    static PENDING = "pending";
    static FULFILLED = "fulfilled";
    static REJECTED = "rejected";
	promiseCallbacks = [];//用来保存回调
    constructor(executor) {
        this.promiseState = MyPromise.PENDING; //promise初始为pending状态
        this.promiseValue = null;
    	try {
        	executor(this.resolve,this.reject);
    	} catch (error) {
        	this.reject(error);
    	}
     }
   resolve = (value) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       setTimeout(() => {
       	this.promiseValue = value;
       	this.promiseState = MyPromise.FULFILLED;
       	this.promiseCallbacks.forEach(callback => {
           	callback.onfulfilled(value)
       	});
       })
   }
   reject = (reason) => {
       if(this.promiseState !== MyPromise.PENDING ) return;
       setTimeout(() => {
       	this.promiseValue = reason;
       	this.promiseState = MyPromise.REJECTED;
       	this.promiseCallbacks.forEach(callback => {
           	callback.onrejected(reason)
      	});
       })
 	}
}
                                      

经过这样子的改造之后,我们的promise跟原生的输出的顺序就是一样的了。

六、链式调用

我们知道,promise还有一个很重要的特性就是链式调用,可以解决回调地狱的问题。那么链式调用是怎么实现的呢?我们运行下面的代码:

const promise = new Promise((resolve,reject) => {
    resolve();
}).then();
console.log(promise);

我们看到在控制台上输出的是一个promise的实例,也就是说then方法也会返回一个promise,这个promise也有then方法,那当然就可以实现链式调用了。

那我们自己写的promise该怎么实现这段代码呢?看下面:

 then = (onfulfilled,onrejected) => {
       //如果onfulfilled不是函数,将其封装成一个函数
      if(typeof onfulfilled !== 'function') onfulfilled = () => {};
       
       //如果onrejected不是函数,抛出一个错误
    	if(typeof onfulfilled !== 'function') onrejected = () => {throw Error(this.promiseValue)};
     
     	return new MyPromise((resolve,reject) => {
            //如果是pending状态的,将回调函数保存在数组中
            if(this.promiseState === MyPromise.PENDING) {
                this.promiseCallbacks.push({onfulfilled,onrejected});
            }
            //如果是成功状态,执行第一个回调函数
            if(this.promiseState === MyPromise.FULFILLED){
                setTimeout(() => {
                    onfulfilled(this.promiseValue);
                })
           	 }
            //如果是失败状态,执行第二个回调函数
           if(this.promiseState === MyPromise.REJECTED){
               setTimeout(() => {
                   onrejected(this.promiseValue);
             })
           }
        })
   }

如果resolvereject方法返回一个值的,则执行下面的过程。如果resolvereject方法返回一个值,我们需要在MyPromise类外部定义一个方法来处理Promise的解决过程。这个函数我们稍后进行补充。

class MyPromise {
     ...
     then = (onfulfilled,onrejected) => {
       //如果onfulfilled不是函数,将其封装成一个函数
      if(typeof onfulfilled !== 'function') onfulfilled = () => {};
       
       //如果onrejected不是函数,抛出一个错误
    	if(typeof onfulfilled !== 'function') onrejected = () => {throw Error(this.promiseValue)};
     
     	 const thenPrommise =  new MyPromise((resolve,reject) => {
            //如果是pending状态的,将回调函数保存在数组中
            if(this.promiseState === MyPromise.PENDING) {
                this.promiseCallbacks.push({onfulfilled:() => {
          +         const cb = onfulfilled(this.promiseValue);
          +         resolvePromise(thenPrommise,cb,resolve,reject);
                },onrejected:() => {
          +          const cb = onrejected(this.promiseValue);
          +          resolvePromise(thenPrommise,cb,resolve,reject);
                }});
            }
            //如果是成功状态,执行第一个回调函数
            if(this.promiseState === MyPromise.FULFILLED){
                setTimeout(() => {
          +         const cb = onfulfilled(this.promiseValue);
          +         resolvePromise(thenPrommise,cb,resolve,reject);
                })
           	 }
            //如果是失败状态,执行第二个回调函数
           if(this.promiseState === MyPromise.REJECTED){
               setTimeout(() => {
          +       const cb = onrejected(this.promiseValue);
          +       resolvePromise(thenPrommise,cb,resolve,reject);
             })
           }
        })
       return thenPrommise;
   }
}
+ //用来处理Promise解决过程的函数
+ function resolvePromise(thenPrommise, cb, resolve, reject) {}

还有一个地方需要注意的是如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 thenPromise 必须拒绝执行,并返回拒因 e

class MyPromise {
     ...
     then = (onfulfilled,onrejected) => {
       //如果onfulfilled不是函数,将其封装成一个函数
      if(typeof onfulfilled !== 'function') onfulfilled = () => {};
       
       //如果onrejected不是函数,抛出一个错误
    	if(typeof onfulfilled !== 'function') onrejected = () => {throw Error(this.promiseValue)};
     
     	 const thenPrommise =  new MyPromise((resolve,reject) => {
            //如果是pending状态的,将回调函数保存在数组中
            if(this.promiseState === MyPromise.PENDING) {
                this.promiseCallbacks.push({onfulfilled:() => {
                     try {
          +             const cb = onfulfilled(this.promiseValue);
          +          	resolvePromise(thenPrommise,cb,resolve,reject);
          +         }catch(e) {
          +             reject(e);
          +         }
                },onrejected:() => {
          +          try {
          +             const cb = onrejected(this.promiseValue);
          +         	resolvePromise(thenPrommise,cb,resolve,reject);
          +         }catch(e) {
          +             reject(e);
          +         }
                }});
            }
            //如果是成功状态,执行第一个回调函数
            if(this.promiseState === MyPromise.FULFILLED){
                setTimeout(() => {
                    try {
          +             const cb = onfulfilled(this.promiseValue);
          +          	resolvePromise(thenPrommise,cb,resolve,reject);
          +         }catch(e) {
          +              reject(e);
                    }
                })
           	 }
            //如果是失败状态,执行第二个回调函数
           if(this.promiseState === MyPromise.REJECTED){
               setTimeout(() => {
          +         try {
          +          const cb = onrejected(this.promiseValue);
          +          resolvePromise(thenPrommise,cb,resolve,reject);  
          +         } catch(e) {
          +             reject(e);
				}
             })
           }
        })
       return thenPrommise;
   }
}
//用来处理Promise解决过程的函数
function resolvePromise(thenPrommise, cb, resolve, reject) {}

这样一来,我们的then方法就大功告成了。

七、resolvePromise函数的实现

接下来我们看看resolvePromise函数的实现,具体的看下面的代码。

//如果返回的值和promise2是同一个对象,则直接报错
function resolvePromise(promise2, x, resolve, reject) {
    if (x === promise2) {
        return reject(new TypeError('Chaining cycle detected for promise'));
    }

    // 如果 x 为 Promise ,则使 promise2 接受 x 的状态
    if (x instanceof myPromise) {
        if (x.PromiseState === myPromise.PENDING) {
            /**
             *         如果 x 处于等待态, promise 需保持为等待态直至 x 被执行或拒绝
             *         注意"直至 x 被执行或拒绝"这句话,
             *         这句话的意思是:x 被执行x,如果执行的时候拿到一个y,还要继续解析y
             */
            x.then(y => {
                resolvePromise(promise2, y, resolve, reject)
            }, reject);
        } else if (x.PromiseState === myPromise.FULFILLED) {
            //  如果 x 处于执行态,用相同的值执行 promise
            resolve(x.PromiseResult);
        } else if (x.PromiseState === myPromise.REJECTED) {
            //  如果 x 处于拒绝态,用相同的据因拒绝 promise
            reject(x.PromiseResult);
        }
+   } else if (x !== null && ((typeof x === 'object' || (typeof x === 'function')))) {
+       //  如果 x 为对象或函数
+       try {
+           //  把 x.then 赋值给 then
+           var then = x.then;
+       } catch (e) {
+           //  如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise
+           return reject(e);
+       }
+
+       /**
+        *  
+        * 如果 then 是函数,将 x 作为函数的作用域 this 调用之。
+        * 传递两个回调函数作为参数,
+        * 第一个参数叫做 `resolvePromise` ,第二个参数叫做 `rejectPromise`
+        */
+       if (typeof then === 'function') {
+           //  如果 resolvePromise 和 rejectPromise 均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略剩下的调用
+           let called = false; // 避免多次调用
+           try {
+               then.call(
+                   x,
+                   //  如果 resolvePromise 以值 y 为参数被调用,则运行 [[Resolve]](promise, y)
+                   y => {
+                       if (called) return;
+                       called = true;
+                       resolvePromise(promise2, y, resolve, reject);
+                   },
+                   // 2.3.3.3.2 如果 rejectPromise 以据因 r 为参数被调用,则以据因 r 拒绝 promise
+                   r => {
+                       if (called) return;
+                       called = true;
+                       reject(r);
+                   }
+               )
+           } catch (e) {
+               /**
+                *  如果调用 then 方法抛出了异常 e
+                *  如果 resolvePromise 或 rejectPromise 已经被调用,则忽略之
+                */
+               if (called) return;
+               called = true;
+
+               /**
+                *  否则以 e 为据因拒绝 promise
+                */
+               reject(e);
+           }
+       } else {
+           //  如果 then 不是函数,以 x 为参数执行 promise
+           resolve(x);
+       }
+   } else {
+       // 如果 x 不为对象或者函数,以 x 为参数执行 promise
+       return resolve(x);
+   }
}

八、总结

经过层层努力,一个我们自己写的promise就写好了。当然,promise中还有很多其他的方法,比如catchfinallyall方法等,这些方法我们有机会会继续将其完善的。