手写Promise?谁爱写谁写!

635 阅读12分钟

手写Promise

Promise规范

promisesaplus.com/ PromiseA+规范

A+规范只有then方法,没有catch、等

Promise 类设计

class MyPromise {}
function MyPromise() {}

两种方式,我选第一种

构造函数constructor设计

实现:

  1. 让executor函数执行起来
  2. 定义状态常量
  3. 定义resolve,reject回调,执行的时候改变状态
const STATUE_PENDING = 'pending'
const STATUE_FULFILLED = 'fulfilled'
const STATUS_REJECTED = 'rejected'

class MyPromise {
  constructor(executor) {
    // 保存状态与值
    this.status = STATUE_PENDING  
    // 由于后面的then方法可能会用到这些参数值,需要保存起来
    this.value = undefined
    this.reason = undefined
	
    // 定义resolve回调
    const resolve = (value) => {
      // 改变状态并保存值
      this.status = STATUE_FULFILLED
      this.value = value
      console.log("resolve执行", value);
    }
	// 定义reject回调
    const reject = (reason) => {
      // 改变状态并保存值
      this.status = STATUS_REJECTED
      this.reason = reason
      console.log("reject执行", reason);
    }

    executor(resolve, reject)
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("pending~");
  resolve("111")
  reject("222")
})
  1. 为了不让resolve,reject回调可以同时执行,我们需要加一个判断,只有状态为pending的时候才执行回调
    const resolve = (value) => {
      if (this.status === STATUE_PENDING) {  // 加一个判断
        this.status = STATUE_FULFILLED
        this.value = value
        console.log("resolve执行", value);
      }
    }

    const reject = (reason) => {
      if (this.status === STATUE_PENDING) { // 加一个判断
        this.status = STATUS_REJECTED
        this.reason = reason
        console.log("reject执行", reason);
      }
    }

then 方法的实现

简单实现

  1. then方法接收两个参数,分别是成功时的回调onFulfilled,失败时的回调onRejected
  2. 把回调保存到当前的promise实例,并在对应的resolve,reject回调时执行
class MyPromise {
  constructor(executor) {
    this.status = STATUE_PENDING
    this.value = undefined
    this.reason = undefined

    const resolve = (value) => {
      if (this.status === STATUE_PENDING) {
        this.status = STATUE_FULFILLED
        this.value = value
        console.log("resolve执行", value);
        this.onFulfilled(this.value) // 在这里执行
      }
    }

    const reject = (reason) => {
      if (this.status === STATUE_PENDING) {
        this.status = STATUS_REJECTED
        this.reason = reason
        console.log("reject执行", reason);
        this.onRejected(this.reason)  // 在这里执行
      }
    }

    executor(resolve, reject)
  }

  then(onFulfilled, onRejected) {
    this.onFulfilled = onFulfilled  // 保存方法
    this.onRejected = onRejected // 保存方法
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("pending~");
  resolve("111")
  reject("222")
})

promise.then(res => {
  console.log("res: ", res);
}, err => {
  console.log("err: ", err);
})

这时候我们会发现,报错了:this.onFulfilled is not a function

为什么??

我们捋一捋代码的执行过程就可以发现,当执行resolve("111") 的时候,都还没有到then那一步,也就是说还没执行then方法,那么怎么可能会有 onFulfilled, onRejected 方法呢!

这时候我们就用到了一个方法:queueMicrotask()

MDN:developer.mozilla.org/en-US/docs/…

简单来说,这个方法可以把我们传入的方法加入到微任务队列,让它延迟到当前主线程的任务执行完之后再执行

所以可以在resolve方法执行的时候,先不执行onFulfilled,把它加入到微任务队列,接着就会继续执行下面的then方法,这时候就有onFulfilled, onRejected 方法了,最后主线程任务执行完,再执行微任务队列中的 onFulfilled,,(reject同理)

    const resolve = (value) => {
      if (this.status === STATUE_PENDING) {
        queueMicrotask(() => {   // 加入到微任务队列
          this.status = STATUE_FULFILLED
          this.value = value
          this.onFulfilled(this.value)
        })
      }
    }

    const reject = (reason) => {
      if (this.status === STATUE_PENDING) {
        queueMicrotask(() => {  // 加入到微任务队列
          this.status = STATUS_REJECTED
          this.reason = reason
          this.onRejected(this.reason)
        })
      }
    }

但是这个时候又出现了一个问题,resolve和reject可以同时调用了

因为我们执行resolve的实现,加入到微任务队列,因此状态没有被改变,依然是pending

接着执行reject,判断状态是pending,所以也加入到微任务队列了

解决:在执行微任务的代码一开始加入一个判断,如果状态已经不是pending了,直接return出去,停止执行

    const resolve = (value) => {
      if (this.status === STATUE_PENDING) {
        queueMicrotask(() => {  
          if (this.status !== STATUE_PENDING) return  // 添加判断
          this.status = STATUE_FULFILLED
          this.value = value
          this.onFulfilled(this.value)
        })
      }
    }

    const reject = (reason) => {
      if (this.status === STATUE_PENDING) {
        queueMicrotask(() => {  
          if (this.status !== STATUE_PENDING) return // 添加判断
          this.status = STATUS_REJECTED
          this.reason = reason
          this.onRejected(this.reason)
        })
      }
    }

当然,有人可能会说把状态改变放到微任务外面不就行了吗?

不行!!这样在后面实现链式调用会出现问题

你后面可以试一下,多个then执行和链式调用一起的时候,执行顺序是有问题的

至于为什么,那就自己捋一捋整个代码的执行顺序叭

同时调用多个then的实现

上面的实现是不能同时调用多个then的

promise.then(res => {
  console.log("res: ", res);
}, err => {
  console.log("err: ", err);
})

promise.then(res => {
  console.log("res2: ", res);
}, err => {
  console.log("err2: ", err);
})

后面的then会覆盖前面的,因此只会执行 res2 或者 err2

实现思路:我们需要把then传入的回调保存到一个数组,到时候一起执行

class MyPromise {
  constructor(executor) {
    this.status = STATUE_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledCallbacks = [] // 定义数组存放成功的回调
    this.onRejectedCallbacks = [] // 定义数组存放失败的回调

    const resolve = (value) => {
      if (this.status === STATUE_PENDING) {
        queueMicrotask(() => {   // 加入到微任务队列
          if (this.status !== STATUE_PENDING) return
          this.status = STATUE_FULFILLED
          this.value = value
          // 用forEach遍历执行数组中的回调 			
          this.onFulfilledCallbacks.forEach(fn => {  
            fn(this.value)
          })
        })
      }
    }

    const reject = (reason) => {
      if (this.status === STATUE_PENDING) {
        queueMicrotask(() => {  // 加入到微任务队列
          if (this.status !== STATUE_PENDING) return
          this.status = STATUS_REJECTED
          this.reason = reason
          // 用forEach遍历执行数组中的回调
          this.onRejectedCallbacks.forEach(fn => {
            fn(this.reason)
          })
        })
      }
    }

    executor(resolve, reject)
  }

  then(onFulfilled, onRejected) {
    this.onFulfilledCallbacks.push(onFulfilled)  // 保存到数组
    this.onRejectedCallbacks.push(onRejected) 
  }
}

const promise = new MyPromise((resolve, reject) => {
  console.log("pending~");
  resolve("111")
  reject("222")
})

promise.then(res => {
  console.log("res: ", res);
}, err => {
  console.log("err: ", err);
})

promise.then(res => {
  console.log("res2: ", res);
}, err => {
  console.log("err2: ", err);
})

延迟调用then

还有一种情况:resolve或reject执行完之后,延迟执行then

const promise = new MyPromise((resolve, reject) => {
  console.log("pending~");
  resolve("111")
  // reject("222")
})

setTimeout(() => {
  promise.then(res => {
    console.log("res3: ", res);
  }, err => {
    console.log("err3: ", err);
  })
}, 1000)

setTimeout 会在主线程的任务执行完,并且微任务队列也执行完后才执行

捋一捋执行顺序:

  1. 首先主线程 resolve("111")执行,先改变状态为fulfilled,保存value,然后在微任务队列中加入一个任务

    image.png
  2. 然后继续往下,setTimeout 被加入到宏任务队列,并未执行then

  3. 主线程任务执行完,执行微任务队列中的任务,遍历数组中的函数并执行,但我们可以看到,前面then没有执行,数组中并没有对应回调,所以没有执行

  4. 接着执行宏任务队列中setTimeout,也就是then方法被执行,

    image.png

    这个时候才把回调加入数组。。。任务结束

因此可以想到实现思路:在then方法中加入判断,如果当前状态是确定的,(fulfilled或rejected),那么直接执行这个回调,不用添加到数组

  then(onFulfilled, onRejected) {
    if (this.status === STATUE_FULFILLED && onFulfilled) {
      onFulfilled(this.value)
    }
    if (this.status === STATUS_REJECTED && onRejected) {
      onRejected(this.reason)
    }

    if (this.status === STATUE_PENDING) {
      this.onFulfilledCallbacks.push(onFulfilled) 
      this.onRejectedCallbacks.push(onRejected) 
    }
  }

链式调用then

then需要返回一个promise,后面才能继续调用then

并且下一次的then是在上次回调执行完之后才执行的,而且需要拿到上次onFulfilled/onRejected 执行完之后的结果,再去执行resolve,reject

  then(onFulfilled, onRejected) {
    if (this.status === STATUE_FULFILLED && onFulfilled) {
      onFulfilled(this.value)
    }
    if (this.status === STATUS_REJECTED && onRejected) {
      onRejected(this.reason)
    }

    if (this.status === STATUE_PENDING) {
      this.onFulfilledCallbacks.push(onFulfilled) 
      this.onRejectedCallbacks.push(onRejected) 
    }

    return new MyPromise((resolve, reject) => {
      resolve() // 这里需要拿到上次回调的结果并且传进去
      reject()
    })
  }

现在有个问题,就是怎么拿到上次执行的结果值?

image.png

思路:把上面那一坨代码放到new里面执行,这样就让里边具备了拿到返回结果的能力

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.status === STATUE_FULFILLED && onFulfilled) {
        // 比如这里就可以拿到结果
        const value = onFulfilled(this.value)
        // 然后再执行(这里已经是下一个promise的resolve了)
        resolve(value)
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        const reason = onRejected(this.reason)
        // 注意这里调用的应该是resolve,除非上一次的错误回调函数抛出了错误
        resolve(reason)
      }
  
      if (this.status === STATUE_PENDING) {
        this.onFulfilledCallbacks.push(onFulfilled) 
        this.onRejectedCallbacks.push(onRejected) 
      }
    })
  }

因为即使我们不链式调用,里面的代码还是会执行的,我们只是想拿到想要的结果,并且在某个时机调用 resolve, reject

两种情况都调用resolve?那什么时候调用reject呢?

我们知道,只有在上次的then中抛出异常了,下次才会执行reject

所以我们再改进一下:使用try...catch

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.status === STATUE_FULFILLED && onFulfilled) {
        try {
          const value = onFulfilled(this.value)
          resolve(value)
        } catch (err) {
          reject(err)
        }
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        try {
          const reason = onRejected(this.reason)
          resolve(reason)
        } catch (err) {
          reject(err)
        }
      }
  
      if (this.status === STATUE_PENDING) {
        this.onFulfilledCallbacks.push(onFulfilled) 
        this.onRejectedCallbacks.push(onRejected) 
      }
    })
  }

上面都是在状态已经确定之后的情况,我们知道在状态为pending的时候,我们是把回调保存到数组,然后在上面的resolve、reject中遍历数组执行的

          this.onFulfilledCallbacks.forEach(fn => {  
            let value = fn(this.value)  // 在这里执行的
          })

那这个执行结果怎么拿到呢然后传给下面的resolve、reject呢?

解决方案:改进我们添加到数组的方式

      if (this.status === STATUE_PENDING) {
        this.onFulfilledCallbacks.push(() => {
          onFulfilled()
        }) 
        this.onRejectedCallbacks.push(() => {
          onRejected()
        }) 
      }

我们不直接把回调添加到数组,而是使用一个函数包裹起来,那么到时上面遍历执行的就是这个包裹的函数,然后我们在这里内部执行onFulfilled,就可以在这里拿到onFulfilled的执行结果

      if (this.status === STATUE_PENDING) {
        this.onFulfilledCallbacks.push(() => {
          const value = onFulfilled(this.value)
          resolve(value)
        }) 
        this.onRejectedCallbacks.push(() => {
          const reason = onRejected(this.reason)
          resolve(reason)
        }) 
      }

同理,try...catch改进一下

      if (this.status === STATUE_PENDING) {
        this.onFulfilledCallbacks.push(() => {
          try {
            const value = onFulfilled(this.value)
            resolve(value)
          } catch (err) {
            reject(err)
          }
        }) 
        this.onRejectedCallbacks.push(() => {
          try {
            const reason = onRejected(this.reason)
            resolve(reason)
          } catch (err) {
            reject(err)
          }
        }) 
      }

测试的时候发现,有一种情况我们没有处理

const promise = new MyPromise((resolve, reject) => {
  console.log("pending~");
  // resolve("111")
  // reject("222")
  throw new Error("error message")
})

改进,在 executor 那里加try...catch,如果抛出了异常直接执行reject

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }

测试:

const promise = new MyPromise((resolve, reject) => {
  console.log("pending~");
  throw new Error("error message")
})

promise.then(res => {
  console.log("res: ", res);
  return "aaa"
}, err => {
  console.log("err: ", err); // 执行这里
  return "bbb"
}).then(res => {
  console.log("res2: ", res); // 然后来到这里
}, err => {
  console.log("err2: ", err);
})
image.png

测试没问题!!

工具函数

到这里then方法基本就实现完了,但是我们发现很多 try...catch的重复代码

我们可以做一个抽取,定义一个工具函数

function execFunctionWithCatchError(exeFn, value, resolve, reject) {
  try {
    const result = exeFn(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

然后优化then方法:

  then(onFulfilled, onRejected) {
    return new MyPromise((resolve, reject) => {
      if (this.status === STATUE_FULFILLED && onFulfilled) {
        // try {
        //   const value = onFulfilled(this.value)
        //   resolve(value)
        // } catch (err) {
        //   reject(err)
        // }
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
  
      if (this.status === STATUE_PENDING) {
        this.onFulfilledCallbacks.push(() => {
          execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
        }) 
        this.onRejectedCallbacks.push(() => {
          execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
        }) 
      }
    })
  }

到此符合A+规范的promise基本编写完成,下面是其他的方法,是在ES6的promise才有的

catch 方法的实现

catch接收一个参数,也就是失败的回调,因为catch实际上就相当于语法糖,而且也是返回一个新的promise,所以我们可以直接调用then

  catch(onRejected) {
    return this.then(undefined, onRejected)
  }

测试:

const promise = new MyPromise((resolve, reject) => {
  console.log("pending~");
  // resolve(111)  
  reject(222)
})

promise.then(res => {
  console.log("res: ", res);
  return "aaa"
}).catch(err => {
  console.log("catch", err);
})

额,报错了

image.png

别急,分析原因。

我们可以观察一下,本来我们的失败回调应该是在第一个then中传入的,是作为第一个promise的失败的回调的

promise.then(res => {
  console.log("res: ", res);
  return "aaa"
}, err => {
  console.log("catch", err);
}).catch()

但是现在我们写到catch里面,意味着这个catch传入的回调是被加入到一个新的promise中,作为新的promise的失败的回调了,所以执行不到这个回调了

promise1 -> undefined

promise2 -> err ={}

那么我们怎么样让promise1执行到err ={} 呢??

实现思路:假如说promise1的失败回调没有值,我们直接抛出去,这样就会来到promise2中失败的回调了

promise1 -> err => {throw err} // 抛出去

promise2 -> err ={} // 就会执行到这里

还有一个地方是,既然onFulfilled或onRejected可能会传进来undefined,那么我们最好加上一个判断

  then(onFulfilled, onRejected) {
    const defaultOnRejected = err => { throw err }  // 添加部分
    onRejected = onRejected || defaultOnRejected

    return new MyPromise((resolve, reject) => {
      if (this.status === STATUE_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
  
      if (this.status === STATUE_PENDING) {
        if (onFulfilled) this.onFulfilledCallbacks.push(() => {
          execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
        }) 
        if (onRejected) this.onRejectedCallbacks.push(() => {
          execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
        }) 
      }
    })
  }

finally 方法的实现

接收一个参数,无论成功或失败,最后都会执行

也就是说,成功与失败的回调都是你传入的那个函数

  // finally
  finally(onFinally) {
    return this.then(() => {
      onFinally()
    }, () => {
      onFinally()
    })
  }

但是还会有一个问题

const promise = new MyPromise((resolve, reject) => {
  console.log("pending~");
  resolve(111)  // 调用resolve有问题
  // reject(222) 调用reject没问题
})

promise.then(res => {
  console.log("res: ", res); // 圈1
}).catch(err => {
  console.log("catch", err);// 圈2
}).finally(() => {
  console.log('finally'); // 圈3
})

分析:捋一捋

如果上面是resolve的话,那么就会执行圈1,然后来到promise2的成功回调

promise1:成功回调是 圈1,失败回调是我们默认的reject

promise2:没有成功回调,失败回调是圈2,

​ 没有成功回调,这时候就会出错了,后面也不会继续执行了,因此要给默认的成功回调 value => { return value }

然后才会执行finally的第一个回调

  then(onFulfilled, onRejected) {
    const defaultOnRejected = err => { throw err }
    onRejected = onRejected || defaultOnRejected

    // 添加部分
    const defaultOnFulfilled = value => { return value }
    onFulfilled = onFulfilled || defaultOnFulfilled
	
    // 来到这里就可以保证 onRejected,onFulfilled 是有值的了,所以下面的判断也可以不要了
    return new MyPromise((resolve, reject) => {
      if (this.status === STATUE_FULFILLED) {  // 改了这里
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === STATUS_REJECTED) { // 改了这里
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
  
      if (this.status === STATUE_PENDING) {
        if (onFulfilled) this.onFulfilledCallbacks.push(() => {
          execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
        }) 
        if (onRejected) this.onRejectedCallbacks.push(() => {
          execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
        }) 
      }
    })
  }

resolve reject 类方法的实现

resolve 类方法本质就是new了一个 promise,然后直接调用resolve

reject同理

  static resolve(value) {
    return new MyPromise((resolve) => resolve(value))
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => reject(reason))
  }

测试:

MyPromise.resolve(123).then(res => {
  console.log(res); // 123
})

all 方法的实现

all方法接收一个promise数组,同样返回一个promise

关键思路:什么时候要执行resolve, 什么时候要执行reject

  static all(promises) {
    return new MyPromise((resolve, reject) => {
      const values = [] // 定义结果数组
      promises.forEach(promise => {
        promise.then(res => {
          values.push(res)
		// 当结果的个数等于传入promise个数的时候,表示已经执行完了,然后再回调resolve
          if (values.length === promises.length) {
            resolve(values)
          }
        }, err => {
          reject(err) // 失败直接执行回调reject
        })
      })
    })
  }

测试:

const p1 = new MyPromise((resolve) => {
  setTimeout(() => {
    resolve("111")
  }, 1000);
})
const p2 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve("222")
    // reject("222")
  }, 2000);
})

const p3 = new MyPromise((resolve) => {
  setTimeout(() => {
    resolve("333")
  }, 3000);
})

MyPromise.all([p1, p2, p3]).then(res => {
  console.log(res); // ['111', '222', '333']
}, err => {
  console.log(err);  // 如果p2调用reject,就会执行这里,输出 222
})

allSettled 方法的实现

与all类型,区别就是无论成功与否都会把结果保存到数组

测试:

const p1 = new MyPromise((resolve) => {
  setTimeout(() => {
    resolve("111")
  }, 1000);
})
const p2 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject("222")
    // reject("222")
  }, 2000);
})

const p3 = new MyPromise((resolve) => {
  setTimeout(() => {
    resolve("333")
  }, 3000);
})

MyPromise.allSettled([p1, p2, p3]).then(res => {
  console.log(res);
})
image.png

race 方法的实现

只要状态改变就执行回调

  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        // promise.then(res => {
        //   resolve(res)
        // }, err => {
        //   reject(err)
        // })
        // 也可以这么写
        promise.then(resolve, reject)
      })
    })
  }

any 方法的实现

等到第一个fulfilled状态,才执行resolve回调

如果全都是rejected状态,那么抛出异常

  static any(promises) {
    const reasons = []
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        }, err => {
          reasons.push(err)
          // 当全部promise执行完之后
          if (reasons.length === promises.length) {
            reject(new AggregateError(reasons))
          }
        })
      })
    })
  }

测试全都是reject的情况

const p1 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject("111")
  }, 1000);
})
const p2 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject("222")
  }, 2000);
})

const p3 = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    reject("333")
  }, 3000);
})

MyPromise.any([p1, p2, p3]).then(res => {
  console.log(res);
}, err => {
  console.log(err, err.errors);
})
image.png

到此,手写promise就差不多大功告成啦!

完整代码

const STATUE_PENDING = 'pending'
const STATUE_FULFILLED = 'fulfilled'
const STATUS_REJECTED = 'rejected'

function execFunctionWithCatchError(exeFn, value, resolve, reject) {
  try {
    const result = exeFn(value)
    resolve(result)
  } catch (err) {
    reject(err)
  }
}

class MyPromise {
  constructor(executor) {
    this.status = STATUE_PENDING
    this.value = undefined
    this.reason = undefined
    this.onFulfilledCallbacks = [] // 定义数组存放成功的回调
    this.onRejectedCallbacks = [] // 定义数组存放失败的回调

    const resolve = (value) => {
      if (this.status === STATUE_PENDING) {
        queueMicrotask(() => {   // 加入到微任务队列
          if (this.status !== STATUE_PENDING) return
          this.status = STATUE_FULFILLED
          this.value = value
          // 用forEach遍历执行数组中的回调 			
          this.onFulfilledCallbacks.forEach(fn => {  
            fn(this.value)
          })
        })
      }
    }

    const reject = (reason) => {
      if (this.status === STATUE_PENDING) {
        queueMicrotask(() => {  // 加入到微任务队列
          if (this.status !== STATUE_PENDING) return
          this.status = STATUS_REJECTED
          this.reason = reason
          // 用forEach遍历执行数组中的回调
          this.onRejectedCallbacks.forEach(fn => {
            fn(this.reason)
          })
        })
      }
    }

    try {
      executor(resolve, reject)
    } catch (err) {
      reject(err)
    }
  }

  then(onFulfilled, onRejected) {
    const defaultOnRejected = err => { throw err }
    onRejected = onRejected || defaultOnRejected

    const defaultOnFulfilled = value => { return value }
    onFulfilled = onFulfilled || defaultOnFulfilled

    return new MyPromise((resolve, reject) => {
      if (this.status === STATUE_FULFILLED && onFulfilled) {
        execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
      }
      if (this.status === STATUS_REJECTED && onRejected) {
        execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
      }
  
      if (this.status === STATUE_PENDING) {
        if (onFulfilled) this.onFulfilledCallbacks.push(() => {
          execFunctionWithCatchError(onFulfilled, this.value, resolve, reject)
        }) 
        if (onRejected) this.onRejectedCallbacks.push(() => {
          execFunctionWithCatchError(onRejected, this.reason, resolve, reject)
        }) 
      }
    })
  }

  // catch
  catch(onRejected) {
    return this.then(undefined, onRejected)
  }

  // finally
  finally(onFinally) {
    return this.then(() => {
      onFinally()
    }, () => {
      onFinally()
    })
  }

  static resolve(value) {
    return new MyPromise((resolve) => resolve(value))
  }

  static reject(reason) {
    return new MyPromise((resolve, reject) => reject(reason))
  }

  static all(promises) {
    return new MyPromise((resolve, reject) => {
      const values = [] // 定义结果数组
      promises.forEach(promise => {
        promise.then(res => {
          values.push(res)
          if (values.length === promises.length) {
            resolve(values)
          }
        }, err => {
          reject(err)
        })
      })
    })
  }

  static allSettled(promises) {
    return new MyPromise((resolve, reject) => {
      const values = []
      promises.forEach(promise => {
        promise.then(res => {
          values.push({status: STATUE_FULFILLED, value: res})
          if (values.length === promises.length) {
            resolve(values)
          }
        }, err => {
          values.push({status: STATUS_REJECTED, value: err})
          if (values.length === promises.length) {
            resolve(values) // 注意这里还是执行resolve
          }
        })
      })
    })
  }

  static race(promises) {
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(resolve, reject)
      })
    })
  }

  static any(promises) {
    const reasons = []
    return new MyPromise((resolve, reject) => {
      promises.forEach(promise => {
        promise.then(res => {
          resolve(res)
        }, err => {
          reasons.push(err)
          // 当全部promise执行完之后
          if (reasons.length === promises.length) {
            reject(new AggregateError(reasons))
          }
        })
      })
    })
  }
}