手写Promise 理解promise底层原理

本文参考了此博客,在网上浏览了很多关于Promise的相关资料,promise可以说是JavaScript的重难点了,其中,很是感谢阮一峰老师的博客讲解以及MDN上的文档教程

如对Promise不太熟悉的同学,可以先浏览Promise工作原理分析,如有不同意见,欢迎讨论,一起进步。

Promise基本流程

function doSomething(){
    var p1 = new Promise(function (resolve, reject) {
        setTimeout(()=>{	//setTimeout1
            console.log('Start do something')
            resolve('Success!')
        },1000)
    })
    return p1
}
function successCallback(data){
    var p2= new Promise(function (resolve, reject) {
        setTimeout(()=>{	//setTimeout2
            console.log(data)
            resolve()
        },1000)
    })
    return p2
}
function failCallback(data){
    var p3 = new Promise(function (resolve, reject) {
        setTimeout(function () {
            console.log('Error1!')
            resolve()		//setTimeout3
        },1000)
    })
    return p3
}

//接下来去调用一下
doSomething()			//promise1
	.then(				
		(data)=>{ 		//promise2
    	return successCallback(data)},
		(data)=>{
    	return failCallback(data)}
    )
	.then(()=>{			//promise3
    return new Promise((resolve,rejected)=>{
        rejected('Unknown Error')
    })
})
	.catch(res=>{		//promise4
    console.log(res)
})

输出:

Start do something
Success!
Unknown Error

过程:

  • 我们来看一看这个promise链,首先执行了doSomething(),此方法返回了p1,并且在p1刚建立之时,此promise链就开始执行。
  • 当setTimeout1执行完之后(即setTimeout1中的resolve(‘Success!’)执行之后),p1的状态会由pending->fulfilled,然后调用then()方法,因为promise1已经fulfilled,所以,这里将调用then()方法中的第一个函数对象,在第一个函数对象中执行了successCallback(data)并返回了promise2。
  • 此时promise2的状态为pending,在setTimeout2中执行了 resolve()之后,其状态会由pending->fulfilled。
  • 然后再调用then()方法,这时候会生成promise3,其状态被设置为rejected,该异常会沿着promise链向下传递,最终被catch()捕获处理。

构造函数Promise必须接受一个函数对象作为参数,我们称其为handle,handle又包含了resolve和reject两个参数,这两个参数都是函数对象。

定义一个判断变量是否为函数的方法,后面会用到:

// 判断变量否为function
const isFunction = variable => typeof variable === 'function'

MyPromise实现promise功能

1. constructor

首先我们定义一个MyPromise的class,它接收一个函数handle作为参数

class MyPromise {
  constructor (handle) {
    if (!isFunction(handle)) {
      throw new Error('MyPromise must accept a function as a parameter')
    }
  }
}

我们从上方的过程中可以知道,promise主体执行异步程序,然后根据是否完成异步程序设置promise的状态,然后根据promise的状态调用then()方法。

所以,我们也为MyPromise添加一个状态标识

  • Pending(进行中)
  • Fulfilled(已成功)
  • Rejected(已失败)

状态只能由 Pending 变为 Fulfilled 或由 Pending 变为 Rejected ,且状态改变之后不会在发生变化,会一直保持这个状态。

2. resolve和reject

resolve和reject做了什么?

  • resolve : 将Promise对象的状态从 Pending(进行中) 变为 Fulfilled(已成功)
  • reject : 将Promise对象的状态从 Pending(进行中) 变为 Rejected(已失败)
  • resolve 和 reject 都可以传入任意类型的值作为实参,表示 Promise 对象成功(Fulfilled)和失败(Rejected)的值
// 定义Promise的三种状态常量
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

为MyPromise添加状态和值,并添加状态改变的执行逻辑:
注意: MyPromise的状态只能改变一次,即状态改变之前MyPromise的状态只能是PENDING

class MyPromise {
  constructor (handle) {
    if (!isFunction(handle)) {
      throw new Error('MyPromise must accept a function as a parameter')
    }
    // 添加状态
    this._status = PENDING
    // 添加状态
    this._value = undefined
    // 执行handle
    try {
      handle(this._resolve.bind(this), this._reject.bind(this)) 
    } catch (err) {
      this._reject(err)
    }
  }
  // 添加resovle时执行的函数
  _resolve (val) {
    if (this._status !== PENDING) return
    this._status = FULFILLED
    this._value = val
  }
  // 添加reject时执行的函数
  _reject (err) { 
    if (this._status !== PENDING) return
    this._status = REJECTED
    this._value = err
  }
}

这里我们需要理解:

handle(this._resolve.bind(this),this._reject.bind(this)) 

我之前阅读这一句代码时陷入了思想误区,这里,我将详细展开为什么要这样写。

观察如下代码:

class myTest{
    constructor(handle) {
        this._sum = undefined
        handle(this._add.bind(this)) 
    }

    _add(a,b){
        this._sum = a + b
        return this._sum
    }

}

let test = new myTest((doSomething)=>{
    let [a, b] = [1, 2]
    console.log(doSomething(a,b))
})

在创建myTest时,传入了一个箭头函数:

(doSomething)=>{let [a, b] = [1, 2];console.log(doSomething(a,b))}

这个箭头函数就是myTest中的handle,然后调用了handle(this._add.bind(this)),这里向handle传入的参数为this._add函数对象,也就是说,这个箭头函数中的doSomething被赋值为了this._add。
平时我们常见到的参数赋值都是实例变量的赋值,而这里是函数变量的赋值,所以有一点难以理解,但是其实和实例变量赋值是一样的思想。
这里还涉及了this指向的知识点,bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。如有疑惑可以查看我的这一篇博客

3. then()

观察promise中的then()

我们已经知道promise的then()方法会接收两个函数对象作为参数,分别对应着promise状态为onFulfilledonRejected的回调函数

promise.then(onFulfilled, onRejected)
  • 如果onFulfilled或onRejected不是函数,其必须忽略。
  • then() 方法会返回一个新的promise对象,因此promise支持链式调用:
promise1.then(onFulfilled1, onRejected1).then(onFulfilled2, onRejected2);
  • 如果onFulfilled1onRejected1 return了一个不是promise类型的值,例如string,那么promise1.then(onFulfilled1, onRejected1)直接把该返回值作为返回的promise对象的值,这个值就是onFulfilled2onRejected2函数的参数。
  • 如果onFulfilled1onRejected1 return了一个promise类型的值(记做promise2),那么then(onFulfilled2, onRejected2) 将等待promise2的状态发生了改变之后,再调用then(onFulfilled2, onRejected2);

更多的promise值的传递和错误捕获机制可以查看这里

在MyPromise中添加then()方法:

// 添加then方法
MyPromise.prototype.then = function (onFulfilled, onRejected) {
  const { _value, _status } = this //参数结构
  switch (_status) {
    // 当状态已经改变时,立即执行对应的回调函数
    case FULFILLED:
      onFulfilled(_value)
      break
    case REJECTED:
      onRejected(_value)
      break
  }
}

思维梳理: 首先then()函数接收了两个函数对象作为参数并根据当前MyPromise的状态选择执行,这里我们通过了一个switch 实现。然后,实现 onFulfilledonRejected的参数传递,我们在前面的学习中知道,promise.then(value=>{},reason=>{})向回调函数传入的参数就是promise对象的值,对应到MyPromise也是MyPromise._value,const { _value, _status } = this就从MyPromise对象中获取到了MyPromise的值和状态。

难点:请注意观察上面的then方法,大家觉得有没有问题呢?看下面的代码:

let p1 = new MyPromise((resolve,reject)=>{
    resolve('OK')
})
let p2 = new MyPromise((resolve,reject)=>{
    setTimeout(()=>{
        	resolve('OK')
    },1000)
})

p1.then((value)=>{
    console.log(value)
},(reason)=>{
    console.warn(reason)
})
p2.then((value)=>{
    console.log(value)
},(reason)=>{
    console.warn(reason)
})

p1和p2唯一的区别是p1直接执行了resolve()方法,而p2执行了一个异步任务,在一段时间后才执行了resolve()方法。
先看p1,在执行p1.then()的时候,p1已经执行了resolve()方法,也就是说p1的状态已经由pending->fulfilled,所以执行then()方法时可以根据状态选择执行哪一个回调函数。
再看p2,在执行then()方法时,p2的状态仍然是pending,这个then方法不会做任何事情,由于状态未改变,switch中找不到对应的回调函数,所以就不会执行回调函数。当setTimeout执行完之后,p2的状态有pending->fulfilled,但此时的then()已经执行完毕,所以也不会执行回调函数。
为了解决这个问题,我们该如何做呢?
在switch中添加一个pending状态?当执行then()时,若MyPromise的状态为pending,我们又该做什么?
为了解决异步任务完成之后我们仍能调用回调函数,我们可以先将then()中的两个函数对象保存起来,所以这需要我们在MyPromise中增加两个任务队列,分别保存成功和失败的回调函数。

        // 添加成功回调函数队列
        this._fulfilledQueues = []
        // 添加失败回调函数队列
        this._rejectedQueues = []

当状态为pending时,将then方法回调函数加入执行队列等待执行

        // 当状态为pending时,将then方法回调函数加入执行队列等待执行
        case PENDING:
            this._fulfilledQueues.push(onFulfilled)
            this._rejectedQueues.push(onRejected)
            break

为什么用 [ ] 来保存回调而不是用一个 {字典} 来保存呢?观察下面的代码

        //保存回调
        this._callback={}
        case PENDING:
            this._callback = {
                onFulfilled:onFulfilled,
                onRejected:onRejected
            }
	let p2 = new MyPromise((resolve,reject)=>{
	    setTimeout(()=>{
	        	resolve('OK')
	    },1000)
	})
	
	p2.then((value)=>{
	    console.log(value)
	},(reason)=>{
	    console.warn(reason)
	})
	p2.then((value)=>{
	    console.log(value+'then second callback')
	},(reason)=>{
	    console.warn(reason)
	})

这里有两个p2的promise链,也就是说当p2的状态改变后,着两条链都会继续进行下去,如果使用字典,那么第一个then()的回调就被第二个then()覆盖掉了
(这里保存回调有多种实现,看大家的喜好,只要全部保存下来并且不会覆盖就可以)
现在问题又来了,我们保存了回调函数,又该什么时候执行呢?
当MyPromise状态改变的时候!=>也就是调用_resolve()或_reject()的时候,所以我们需要更新MyPromise的_resolve()和_reject()。


    _resolve (val) {
        if (this._status !== PENDING) return
        this._status = FULFILLED
        this._value = val
        let callback
        while (callback = this._fulfilledQueues.shift()){
            callback(this._value)
        }
    }

    _reject (err) {
        if (this._status !== PENDING) return
        this._status = REJECTED
        this._value = err
        let callback
        while (callback = this._rejectedQueues.shift()){
            callback(this._value)
        }
    }

继续完善then()方法。
为了保证MyPromise可以链式调用,所以then()方法需要返回一个MyPromise。
我们先看看promise的then()如何返回一个新的promise:

     let p = new Promise((resolve,reject)=>{
         resolve('OK')
     })

     let p1 = p.then(value => {
         return value
     })

     let p2 = p.then(value => {
         return new Promise((resolve, reject)=>{
             resolve('Return a promise')
         })
     })

     let p3 = p.then(value => {
         return new Promise((resolve, reject)=>{
            reject('Error')
         })
     })

     let p4 = p.then(value => {
         return new Promise((resolve, reject)=>{
         })
     })

     let p5 = p.then(value => {
         throw Error('Error!')
     })

     console.log(p1)
     console.log(p2)
     console.log(p3)
     console.log(p4)
     console.log(p5)

手写Promise 理解promise底层原理_第1张图片

  • 当then()方法的回调函数返回一个简单值时,then()方法返回的promise对象的值就是该回调函数返回的值,且返回的promise状态为fulfilled,形如p1;
  • 当then()方法的回调函数返回一个promise(记做p_callback)时,then()方法返回的promise对象的值就是p_callback对象的值,且返回的promise状态和p_callback状态一样,形如p2,p3,p4;
  • 当then()方法中的回调函数抛出一个异常时,then()方法放回的promise对象的值就是其抛出的异常,状态为rejected,形如p5。

根据以上三点,我们来改写MyPromise的then()方法:

MyPromise.prototype.then = function (onFulfilled, onRejected) {
	const self  = this
    return new MyPromise((resolve,reject)=>{
        switch (this._status) {
            // 当状态为pending时,将then方法回调函数加入执行队列等待执行
            case PENDING:
                this._fulfilledQueues.push(onFulfilled)
                this._rejectedQueues.push(onRejected)
                break
            // 当状态已经改变时,立即执行对应的回调函数
            case FULFILLED:
                try {
                    let result = onFulfilled(this._value) //获取到回调函数的结果
                    //根据result来设置返回的MyPromise
                    if(result instanceof MyPromise){
                        //如果回调函数返回了一个MyPromise对象
                        result.then( v => { //v是result执行成功后的_value值
                            resolve(v)  //根据result的状态值来设置返回的MyPromise的状态值和对象值
                        },r => { //r是result执行失败后的_valur值
                            reject(r)
                        })
                    }else {
                        //如果回调函数返回的是一个简单值
                        resolve(result)
                    }
                }catch (e) {
                    //如果回调函数抛出了异常
                    reject(e)
                }
                break
            case REJECTED:
                try {
                    let result = onRejected(this._value) //获取到回调函数的结果
                    //根据result来设置返回的MyPromise
                    if(result instanceof MyPromise){
                        //如果回调函数返回了一个MyPromise对象
                        result.then( v => { //v是result执行成功后的_value值
                            resolve(v)  //根据result的状态值来设置返回的MyPromise的状态值和对象值
                        },r => { //r是result执行失败后的_valur值
                            reject(r)
                        })
                    }else {
                        //如果回调函数返回的是一个简单值
                        resolve(result)
                    }
                }catch (e) {
                    //如果回调函数抛出了异常
                    reject(e)
                }
                break
        }
    })
}

在仔细阅读上面的代买之后,不知道大家有没有发现一个问题,我们只修改了同步任务下的then()方法,如果此时MyPromise需要执行一个异步任务:

     let myPromise = new MyPromise((resolve,reject)=>{
        setTimeout(()=>{
            resolve('OK')
        },1000)
     })

     myPromise.then((value)=>{
         return new MyPromise((resolve,reject)=>{
             resolve(value + ' with returning a new MyPromise')
         })
     }).then(value=>{
         console.log(value)
     })

then()方法发现myPromise的状态为PENDING,所以会将回调函数放入数组,而在PENDING分支中并没有对返回的MyPromise对象进行设置。当myPromise的异步任务完成,其状态改变之后,会在_resolve()或_reject()中调用之前存入数组中的回调函数。改变_resolve()和_reject()方法,在_resolve()和_reject()中设置then()方法返回的MyPromise?这样明显很难实现,因为then()方法的返回值和_resolve()、_reject()的作用域都不一样。
所以,不妨换一个思路,之前我们是向数组中直接添加了回调函数:

  case PENDING:
                this._fulfilledQueues.push(onFulfilled)
                this._rejectedQueues.push(onRejected)

现在,我们可以向数组中添加一个包含了回调函数和改变返回的MyPromise对象的混合函数。

MyPromise.prototype.then = function (onFulfilled, onRejected) {
    const self = this
    return new MyPromise((resolve,reject)=>{
        switch (this._status) {
            // 当状态为pending时,将then方法回调函数加入执行队列等待执行
            case PENDING:
                this._fulfilledQueues.push(()=>{
                    try {
                        let result = onFulfilled(self._value)
                        //这里和FULFILLED和REJECTED分支对返回对象的处理相似
                        //根据result来设置返回的MyPromise
                        if(result instanceof MyPromise){
                            //如果回调函数返回了一个MyPromise对象
                            result.then( v => { //v是result执行成功后的_value值
                                resolve(v)  //根据result的状态值来设置返回的MyPromise的状态值和对象值
                            },r => { //r是result执行失败后的_valur值
                                reject(r)
                            })
                        }else {
                            //如果回调函数返回的是一个简单值
                            resolve(result)
                        }
                    }catch (e) {
                        //如果回调函数抛出了异常
                        reject(e)
                    }
                })
                this._rejectedQueues.push(()=>{
                    try {
                        let result = onRejected(self._value)
                        //这里和FULFILLED和REJECTED分支对返回对象的处理相似
                        //根据result来设置返回的MyPromise
                        if(result instanceof MyPromise){
                            //如果回调函数返回了一个MyPromise对象
                            result.then( v => { //v是result执行成功后的_value值
                                resolve(v)  //根据result的状态值来设置返回的MyPromise的状态值和对象值
                            },r => { //r是result执行失败后的_valur值
                                reject(r)
                            })
                        }else {
                            //如果回调函数返回的是一个简单值
                            resolve(result)
                        }
                    }catch (e) {
                        //如果回调函数抛出了异常
                        reject(e)
                    }
                })
                break
            // 当状态已经改变时,立即执行对应的回调函数
            case FULFILLED:
                try {
                    let result = onFulfilled(self._value) //获取到回调函数的结果
                    //根据result来设置返回的MyPromise
                    if(result instanceof MyPromise){
                        //如果回调函数返回了一个MyPromise对象
                        result.then( v => { //v是result执行成功后的_value值
                            resolve(v)  //根据result的状态值来设置返回的MyPromise的状态值和对象值
                        },r => { //r是result执行失败后的_valur值
                            reject(r)
                        })
                    }else {
                        //如果回调函数返回的是一个简单值
                        resolve(result)
                    }
                }catch (e) {
                    //如果回调函数抛出了异常
                    reject(e)
                }
                break
            case REJECTED:
                try {
                    let result = onRejected(self._value) //获取到回调函数的结果
                    //根据result来设置返回的MyPromise
                    if(result instanceof MyPromise){
                        //如果回调函数返回了一个MyPromise对象
                        result.then( v => { //v是result执行成功后的_value值
                            resolve(v)  //根据result的状态值来设置返回的MyPromise的状态值和对象值
                        },r => { //r是result执行失败后的_valur值
                            reject(r)
                        })
                    }else {
                        //如果回调函数返回的是一个简单值
                        resolve(result)
                    }
                }catch (e) {
                    //如果回调函数抛出了异常
                    reject(e)
                }
                break
        }
    })
}

这一部分难以理解,我们需要和前面的then()分析联系起来反复斟酌。

如果MyPromise的状态为rejected,而then()只传入了fulfilled状态对用的回调函数,这有出现了一个新的问题,onRejected is not defined……
所以,我们再完善then(),当只传入一个回调函数的情况下:

MyPromise.prototype.then = function (onFulfilled, onRejected) {
    const self = this
    if (!isFunction(onRejected)){
        onRejected = reason =>{
            throw reason
        }
    }
    return new MyPromise(……)
}

其实,这就是promise的异常渗透机制的实现

现在,我们的then()就算是达到了期望,但是,我们不难发现,在then()方法中,出现了四次try……catch……,而且功能类似,为了方便后期维护,防止代码冗余,我们可以将这段代码封装起来。

MyPromise.prototype.then = function (onFulfilled, onRejected) {
    const self = this
    return new MyPromise((resolve,reject)=>{
        function callback(action){
            try {
                let result = action(self._value) //获取到回调函数的结果
                //根据result来设置返回的MyPromise
                if(result instanceof MyPromise){
                    //如果回调函数返回了一个MyPromise对象
                    result.then( v => { //v是result执行成功后的_value值
                        resolve(v)  //根据result的状态值来设置返回的MyPromise的状态值和对象值
                    },r => { //r是result执行失败后的_valur值
                        reject(r)
                    })
                }else {
                    //如果回调函数返回的是一个简单值
                    resolve(result)
                }
            }catch (e) {
                //如果回调函数抛出了异常
                reject(e)
            }
        }

        switch (this._status) {
            // 当状态为pending时,将then方法回调函数加入执行队列等待执行
            case PENDING:
                this._fulfilledQueues.push(()=>{
                    callback(onFulfilled)
                })
                this._rejectedQueues.push(()=>{
                    callback(onRejected)
                })
                break
            // 当状态已经改变时,立即执行对应的回调函数
            case FULFILLED:
                callback(onFulfilled)
                break
            case REJECTED:
                callback(onRejected)
                break
        }
    })
}

4. catch的实现

Promise.prototype.catch()方法是用于指定发生错误时的回调函数
所以,我们在实现catch时,可以借助then():

MyPromise.prototype.catch = function (onRejected){
    return this.then(undefined,onRejected)
}

5. 添加一些静态方法:

静态resolve():

// 添加静态resolve方法
static resolve (value) {
  // 如果参数是MyPromise实例,直接返回这个实例
  if (value instanceof MyPromise) return value
  return new MyPromise(resolve => resolve(value))
}

静态reject():

// 添加静态reject方法
static reject (value) {
  return new MyPromise((resolve ,reject) => reject(value))
}

静态all()

// 添加静态all方法
static all (list) {
  return new MyPromise((resolve, reject) => {
    /**
     * 返回值的集合
     */
    let values = []
    let count = 0
    for (let [i, p] of list.entries()) {
      // 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
      this.resolve(p).then(res => {
        values[i] = res
        count++
        // 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
        if (count === list.length) resolve(values)
      }, err => {
        // 有一个被rejected时返回的MyPromise状态就变成rejected
        reject(err)
      })
    }
  })
}

静态race()

// 添加静态race方法
static race (list) {
  return new MyPromise((resolve, reject) => {
    for (let p of list) {
      // 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
      this.resolve(p).then(res => {
        resolve(res)
      }, err => {
        reject(err)
      })
    }
  })
}

6. finally()

finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作

finally (callback) {
  return this.then(
    value  => MyPromise.resolve(callback()).then(() => value),
    reason => MyPromise.resolve(callback()).then(() => { throw reason })
  );
};

最后,附上全部代码:

// 判断变量否为function
const isFunction = variable => typeof variable === 'function'

// 定义Promise的三种状态常量
const PENDING = 'PENDING'
const FULFILLED = 'FULFILLED'
const REJECTED = 'REJECTED'

class MyPromise {
    constructor (handle) {
        if (!isFunction(handle)) {
            throw new Error('MyPromise must accept a function as a parameter')
        }
        // 添加状态
        this._status = PENDING
        // 添加状态
        this._value = undefined
        // 添加成功回调函数队列
        this._fulfilledQueues = []
        // 添加失败回调函数队列
        this._rejectedQueues = []
        // //保存回调
        // this._callback={}
        // 执行handle
        try {
            handle(this._resolve.bind(this), this._reject.bind(this))
        } catch (err) {
            this._reject(err)
        }
    }
    // 添加resovle时执行的函数
    _resolve (val) {
        if (this._status !== PENDING) return
        this._status = FULFILLED
        this._value = val
        let callback
        while (callback = this._fulfilledQueues.shift()){
            callback(this._value)
        }
    }
    // 添加reject时执行的函数
    _reject (err) {
        if (this._status !== PENDING) return
        this._status = REJECTED
        this._value = err
        let callback
        while (callback = this._rejectedQueues.shift()){
            callback(this._value)
        }
    }

    // 添加静态resolve方法
    static resolve (value) {
        // 如果参数是MyPromise实例,直接返回这个实例
        if (value instanceof MyPromise) return value
        return new MyPromise(resolve => resolve(value))
    }

    // 添加静态reject方法
    static reject (value) {
        return new MyPromise((resolve ,reject) => reject(value))
    }

    // 添加静态all方法
    static all (list) {
        return new MyPromise((resolve, reject) => {
            /**
             * 返回值的集合
             */
            let values = []
            let count = 0
            for (let [i, p] of list.entries()) {
                // 数组参数如果不是MyPromise实例,先调用MyPromise.resolve
                this.resolve(p).then(res => {
                    values[i] = res
                    count++
                    // 所有状态都变成fulfilled时返回的MyPromise状态就变成fulfilled
                    if (count === list.length) resolve(values)
                }, err => {
                    // 有一个被rejected时返回的MyPromise状态就变成rejected
                    reject(err)
                })
            }
        })
    }

    // 添加静态race方法
    static race (list) {
        return new MyPromise((resolve, reject) => {
            for (let p of list) {
                // 只要有一个实例率先改变状态,新的MyPromise的状态就跟着改变
                this.resolve(p).then(res => {
                    resolve(res)
                }, err => {
                    reject(err)
                })
            }
        })
    }

    finally (callback) {
        return this.then(
            value  => MyPromise.resolve(callback()).then(() => value),
            reason => MyPromise.resolve(callback()).then(() => { throw reason })
        );
    };

}

// 添加then方法
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    const self = this
    if (!isFunction(onRejected)){
        onRejected = reason =>{
            throw reason
        }
    }
    return new MyPromise((resolve,reject)=>{
        function callback(action){
            try {
                let result = action(self._value) //获取到回调函数的结果
                //根据result来设置返回的MyPromise
                if(result instanceof MyPromise){
                    //如果回调函数返回了一个MyPromise对象
                    result.then( v => { //v是result执行成功后的_value值
                        resolve(v)  //根据result的状态值来设置返回的MyPromise的状态值和对象值
                    },r => { //r是result执行失败后的_valur值
                        reject(r)
                    })
                }else {
                    //如果回调函数返回的是一个简单值
                    resolve(result)
                }
            }catch (e) {
                //如果回调函数抛出了异常
                reject(e)
            }
        }

        switch (this._status) {
            // 当状态为pending时,将then方法回调函数加入执行队列等待执行
            case PENDING:
                this._fulfilledQueues.push(()=>{
                    callback(onFulfilled)
                })
                this._rejectedQueues.push(()=>{
                    callback(onRejected)
                })
                break
            // 当状态已经改变时,立即执行对应的回调函数
            case FULFILLED:
                callback(onFulfilled)
                break
            case REJECTED:
                callback(onRejected)
                break
        }
    })
}

MyPromise.prototype.catch = function (onRejected){
    return this.then(undefined,onRejected)
}

你可能感兴趣的