手写实现一个简单的Promise

121 阅读1分钟

手写实现一个简单的Promise

背景: Promise A+

需求

  • 初始化&异步调用
  • then, catch链式调用

实现

class Promise {
  //状态
  state = 'pending' //'pending','fullfilled', 'rejected'
  value = undefined //resolved
  reason = undefined //reject
  
  resolveCallbacks = []
  rejectCallbacks = []
  
  constructor(fn){
    const resolveHandle = (value) => {
      if(this.state === 'pending'){
        this.state = 'fullfilled'
        this.value = value
        this.resolveCallbacks.forEach((fn) => fn(this.value))
      }
    }
    const rejectHandle = (reason) => {
      if(this.state === 'pending'){
        this.state = 'rejected'
        this.reason = reason
        this.rejectCallbacks.forEach((fn) => fn(this.reason))
      }
    }
    try{
      fn(resolveHandle, rejectHandle)
    } catch(err) {
      rejectHandle(err)
    }
  }
  
  then(fn1, fn2) {
    fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
    fn2 = typeof fn2 === 'function' ? fn2 : (e) => e
    
    if(this.state === 'pending'){
      const promise = new MyPromise((resolve, reject) => {
        this.resolveCallbacks.push(() => {
          try{
            const newValue = fn1(this.value)
            resolve(newValue)
          }catch(err){
            reject(err)
          }
        })
        
        this.rejectCallbacks.push(() => {
          try{
            const newReason = fn2(this.reason)
            reject(newReason)
          } catch(err) {
            reject(err)
          }
        })
      })
      return promise
    }
    
   if(this.state === 'fullfilled'){
      const promise = new MyPromise((resolve, reject) => {
           try{
             const newValue = fn1(this.value)
             resolve(newValue)
           } catch(err) {
             reject(err)
           }
      })
      return promise
    }
    
    if(this.state === 'rejected') {
      const promise = new MyPromise((resolve, reject) => {
        try{
          const newReason = f2(this.reason)
          reject(newReason)
        }catch(err) {
          reject(err)
        }
      })
      return promise
    }
  }
  
  catch(fn) {
    return this.then(null, fn)
  }
}