手写promise

const PROMISE_STATUS_PENDING = "pending"
const PROMISE_STATUS_RESLOVE = "resolve"
const PROMISE_STATUS_REJECT = "reject"


const executorFuctionWithErr = function(fn,parmas,reslove,reject) {
  try {
    const value = fn(parmas)
    reslove(value)
  } catch (error) {
    reject(error)
  }
}

class LQpromise {
  constructor(executor) {
    // promise的状态
    this.status = PROMISE_STATUS_PENDING
    // 调resolve时的参数
    this.value = undefined
    // 调reject时的参数
    this.reason = undefined
    // 保存then函数传入的第一个函数(成功时的回调)以便多次调用then
    this.onfulfilledFns = []
    // 保存then函数传入的第二个函数(失败时的回调)
    this.onrejectedFns = []

    const reslove = (value) => {
      // 只有在状态为pending时,才能调用reslove()
      if(this.status  == PROMISE_STATUS_PENDING) {
        // 因为then()里的回调函数需要是微任务,所以将其放在微任务队列
        queueMicrotask(() => {
          if(this.status !== PROMISE_STATUS_PENDING) return
          // 调用reslove()后要将状态改成resolve
          this.status = PROMISE_STATUS_RESLOVE
          this.value = value
          this.onfulfilledFns.forEach(fn => {
            fn(this.value)
          })
        })
      }
    }
    const reject = (reason) => {
      // 只有在状态为pending时,才能调用reject()
      if(this.status  == PROMISE_STATUS_PENDING) {
        // 因为then()里的回调函数需要是微任务,所以将其放在微任务队列
        queueMicrotask(() => {
          if(this.status !== PROMISE_STATUS_PENDING) return
          // 调用reject()后要将状态改成reject
          this.status = PROMISE_STATUS_REJECT
          this.reason = reason
          this.onrejectedFns.forEach(fn => {
            fn(this.reason)
          })
        })
      }
      
    }
    try {
      executor(reslove,reject)
    } catch (error) {
      reject(error)
    }
  }
  then(onfulfilled, onrejected) {
    // 当使用then只传了第一个参数时,给onrejected赋值一个抛出异常的的函数,将异常交给then()返回的LQpromise处理(实现catch方法)
    onrejected = onrejected || (err => {throw err})
    // 当使用then只传了二个参数时,给onfulfilled赋值一个函数,并且将传过来的参数直接返回,交给then()返回的LQpromise处理(实现finaly方法)
    onfulfilled = onfulfilled || (value => value)
    return new LQpromise((reslove,reject) => {
      // onrejected = onrejected || (err => {reject(err)})
      if(this.status  == PROMISE_STATUS_RESLOVE) {
      // 当promise状态已经为resolve时,又调用了then()方法,此时onfulfilled方法需直接执行
        // try {
        //   const value = onfulfilled(this.value)
        //   reslove(value)
        // } catch (error) {
        //   reject(error)
        // }
        executorFuctionWithErr(onfulfilled,this.value,reslove,reject)
      }
      if(this.status  == PROMISE_STATUS_REJECT) {
          // 当promise状态已经为reject时,又调用了then()方法,此时onrejected方法需直接执行
          // try {
          //   const value = onrejected(this.reason)
          //   reslove(value)
          // } catch (error) {
          //   reject(error)
          // }
          executorFuctionWithErr(onrejected,this.reason,reslove,reject)
      }
      if(this.status  == PROMISE_STATUS_PENDING) {
        // 将成功的回调和失败的回调函数放入到对应的数组 这里把传进来的函数用函数在包裹一层,是便于then的链式调用,如果直接push()函数,进去,拿不到函数的返回值再调用reslove()
        if(onfulfilled) {
          this.onfulfilledFns.push(() => {
            // try {
            //   const value = onfulfilled(this.value)
            //   reslove(value)
            // } catch (error) {
            //   reject(error)
            // }
            executorFuctionWithErr(onfulfilled,this.value,reslove,reject)
          })
        }
        if(onrejected) {
          this.onrejectedFns.push(() => {
            // try {
            //   const value = onrejected(this.reason)
            //   reslove(value)
            // } catch (error) {
            //   reject(error)
            // }
            executorFuctionWithErr(onrejected,this.reason,reslove,reject)
          })
        }
      }
    })
  } 
  catch(onrejected) {
    return this.then(undefined,onrejected)
  }
  finally(onfinally) {
    this.then(onfinally,onfinally)
  }
  static reslove(value) {
    return new LQpromise((reslove,reject) => {
      reslove(value)
    })
  }
  static reject(reason) {
    return new LQpromise((reslove,reject) => {
      reject(reason)
    })
  }
  static all(promises) {
    const values = []
    return new LQpromise((reslove,reject) => {
      promises.forEach(promise => {
        promise.then((res) => {
          values.push(res)
          if(values.length === promises.length) {
            reslove(values)
          }
        }).catch(err => {
          reject(err)
        })
      })
    }) 
  }
  static allSettled(promises) {
    const result = []
    return new LQpromise((reslove,reject) => {
      promises.forEach(promise => {
        promise.then(res => {
          result.push({status:PROMISE_STATUS_RESLOVE,value:res})
          if(result.length == promises.length) reslove(result)
        },(err) => {
          result.push({status:PROMISE_STATUS_REJECT,err:err})
          if(result.length == promises.length) reslove(result)
        })
      })
    })
  }
  static race(promises) {
    return new LQpromise((reslove,reject) => {
      promises.forEach(promise => {
        promise.then(res => {
          reslove(res)
        },err => {
          reject(err)
        })
      })
    })
  }
  static any(promises) {
    const errs = []
    return new LQpromise((reslove,reject) => {
      promises.forEach(promise => {
        promise.then((res) => {
          reslove(res)
        },(err) => {
          errs.push(err)
          if(errs.length == promises.length) reject(errs)
        })
      })
    })
  }
}


const promise1 = new LQpromise((reslove,reject) => {
  setTimeout(() => {reject(1)}, 3000);
})
const promise2 = new LQpromise((reslove,reject) => {
  setTimeout(() => {reject(2)}, 2000);
})
const promise3 = new LQpromise((reslove,reject) => {
  setTimeout(() => {reject(3)}, 3000);
})

LQpromise.any([promise1,promise2,promise3]).then((res) => {console.log(res)},(err) => {console.log(err)})
// LQpromise.race([promise1,promise2,promise3]).then((res) => {console.log(res)},(err) => {console.log(err)})
// LQpromise.all([promise1,promise2,promise3]).then((res) => {console.log(res)},(err) => {console.log(err)})
// LQpromise.allSettled([promise1,promise2,promise3]).then((res) => {console.log(res)})

// LQpromise.reslove(111).then((res) => {
//   console.log(res)
// })

// LQpromise.reject(222).catch((err) => {
//   console.log(err)
// })

// const promise = new LQpromise((reslove,reject) => {
//   // console.log(123)
//   // throw new Error("executor err message")
//   // reslove(234)
//   reject(345)
// })

// promise.then((res) => {
//   console.log(res)
// }).catch(err => {
//   console.log(err)
// }).finally((value) => {
//   console.log(value)
// })

// promise.then((res) => {
//   console.log(res)
// }).catch((err) => {
//   // 这样调用catch 是调用第一个then()返回的LQpromise里的catch,是拿不到 promise.catch的 所以要抛出异常,让then()返回的LQpromise里的catch去处理
//   console.log(err)
// })

// promise.then((res) => {
//   console.log('then1',res)
//   throw new Error("err message")
//   return 111
// },(err) => {
//   console.log('err1',err)
//   return err
// }).then((res) => {
//   console.log("第二个then",res)
// },(err) => {
//   console.log('第二个err',err)
// })

// promise.then((res) => {
//   console.log('then2',res)
// },(err) => {
//   console.log('err2',err)
// })

// setTimeout(() => {
//   promise.then((res) => {
//     console.log('then3',res)
//   },(err) => {
//     console.log('err3',err)
//   })
// }, 1000);
posted @ 2022-03-25 14:28  coderlq  阅读(25)  评论(0)    收藏  举报