Promise的简易实现

39 阅读1分钟
class CPromise {
    constructor(func){
        this.status = 'pedding',
        this.value = null,
        this.reason = null,
        this.fullfilledCBS = []
        this.rejectCBS = []
        try {
            func(this.resolve.bind(this), this.reject.bind(this))
        } catch (error) {
            this.reject(error)
        }
    }
    resolve(val){
        this.status = 'fulfilled'
        this.value = val
        this.fullfilledCBS.forEach(cb => cb(this.value))
    }
    reject(reason){
        this.status = 'rejected'
        this.reason = reason
        this.rejectCBS.forEach(cb => cb(this.reason))
    }
    
    then(onFulfilled, onRejected){
        let onFulfilledCB = (res,rej)=>{
           return function(val){
            try {
                let x = onFulfilled(val)
                if(x instanceof CPromise){
                    x.then(res,rej)
                }else{
                    res(x)
                }
            } catch (error) {
                rej(error)
            }
           }
        }
        let onRejectedCB = (res,rej)=>{
            return function(val){
                try {
                    let x = onRejected(val)
                    if(x instanceof CPromise){
                        x.then(res,rej)
                    }else{
                        res(x)
                    }
                } catch (error) {
                    rej(error)
                }
            }
        }
        if(this.status == 'pedding'){
            return new CPromise((resolve,reject)=>{
                this.fullfilledCBS.push(onFulfilledCB(resolve,reject))
                this.rejectCBS.push(onRejectedCB(resolve,reject))
            })
        }
        if(this.status == 'fulfilled'){
            return new CPromise((resolve,reject)=>{
                onFulfilledCB(resolve,reject)(this.value)
            })
        }
        if(this.status == 'rejected'){
            return new CPromise((resolve,reject)=>{
                onRejectedCB(resolve,reject)(this.value)
            })
        }
        
    }
    catch(cb){
        return this.then(null,cb)
    }
    finally(cb){
        return this.then(cb,cb)
    }
}
//调用
new CPromise((resolve,reject)=>{
    setTimeout(() => {
        resolve(1)
    },1000)
}).then((val)=>{
    console.log('fulfilled 1 ',val)
    return val
},(val)=>{
    console.log('rejected 1',val)
    return val
}).then((val)=>{
    console.log('fullfilled 2',val)
    throw 9
},(val)=>{
    console.log('rejected 2',val)
}).catch(e=>{
    console.log('catch',e)
    return e
}).finally((val)=>{
    console.log('finally',val)
    return val
})
class ipromise{
  constructor(fn){
    this.value = null
    this.status = 'pedding'
    this.callback=[]
    this.msg = ''
    
    fn(this.resolve,this.reject)
  }
  resolve = (val)=>{
    if(this.status == 'pedding'){
      this.status = 'resolved'
      this.value = val
      if(this.callback.length){
        this.then(this.callback[0].resolve)
      }
    }
  }
  reject = (msg)=>{
    if(this.status == 'pedding'){
      this.status = 'rejected'
      this.msg = msg
      if(this.callback.length){
        this.then(this.callback[0].reject)
      }
    }
  }
  then(resfn,rejfn){
    if(this.status =='pedding'){
      this.callback.push({
        resolve:resfn
      ,reject:rejfn})
    }
    if(this.status == 'resolved'){
      return new ipromise((resolve,reject)=>{
        const result = resfn(this.value)
        if( result instanceof ipromise){
          return result.then(val=>{
            resolve(val)
          })
        }else{
          resolve(result)
        }
      })
    }
    if(this.status == 'rejected'){
      return new ipromise((resolve,reject)=>{
        const result = rejfn(this.value)
        if(result instanceof ipromise){
          return result.then(val=>{
            resolve(val)
          })
        }else{
          resolve(result)
        }
      })
    }
  }
}