手写一个简易 Promise

221 阅读1分钟

思路

  • 在每一次 .then 使用队列将成功或者失败的函数存起来
  • 调用 resolve 时就执行成功队列的函数
  • 调用 reject 时就执行失败队列的函数

具体代码:

class Promise {
  queue1 = []  // 容纳成功之后要执行的函数
  queue2 = []  // 容纳失败之后要执行的函数
  constructor(fn){  // new Promise2(fn)
    const resolve = (date) => {  // fn 接受 resolve 并在成功之后调用
      setTimeout(()=>{  // 等会执行,否则 queue1 和 queue2 为空
        for(let i=0;i<this.queue1.length;i++){
          this.queue1[i](date)  //遍历成功队列的每一个函数并执行
        }
      })
    }
    
    const reject = (reason) => {
       setTimeout(()=>{
        for(let i=0;i<this.queue2.length;i++){
          this.queue2[i](reason)
        }
      })
    }
    
    fn(resolve,reject) // new Promise() 里面是直接执行的
  }

  then(success,error){  // new Promise(fn).then()
    this.queue1.push(success) // 将成功后要执行的函数放入成功队列
    this.queue2.push(error)  // 将失败后要执行的函数放入失败队列
    return this  // 调用 then 之后还可调用 then
  }
}

测试:

p1 = new Promise((resolve,reject)=>{
  console.log('hi')
  if(Math.random()>0.5){
    resolve('大')
  }else{
    reject('小')
  }
})

p1.then((date)=>{console.log(date+'成功')},(reason)=>{console.log(reason+'失败')})
  .then(()=>{console.log('成功2')},()=>{console.log('失败2')})

结果: "hi" "大成功" "成功2"

有待改进

由于严格模式下: 在执行第一个失败后调用的函数不报错的情况下不会走第二个失败函数的,而是走第二个成功后要执行的函数。

  • 只要执行的是第一个失败后调用的函数,那么接下来的 .then 都是走失败后要执行的函数流程。