promise简单实现

Promise

promise 是一个构造函数,他的参数是一个 function,new promise()时传入的函数会立即执行

  • 特点:维护一个状态机,有 pending,fulfilled,rejected 三种状态,一旦状态改变了后不会再变
  • 作用:链式调用,避免回调函数结构复杂
  • 结构: Promise 中有 all,race,resolve,reject 等方法,Promise.prototype 有 then,catch,finally 等方法



all()

  • 接受 promise 对象,返回所有对象 resolve 的结果,返回结构为数组,是一个 promise 实例
  • 若有 reject,则返回最先 rejected 状态的 reject 结果

race()

  • 返回最先 resolve 或最先 reject 的结果,返返回 promise

then()

  • 接受两个参数,两个参数分别为两个函数,返回 promise 对象
  • 参数一:resolve 时执行;参数二:reject 执行

catch()

  • 接受 reject 参数
  • 也接受发生异常时调用的参数

finally()

  • 无论状态是什么都会执行的函数


实现

  1. 基础框架
function MyPromise(fn){
   function resolve(data){
       console.log(data)
   }

   function reject(data){
       console.log(data)
   }

  try{
   fn(resolve,reject)
  }catch(e){
      reject(e)
  }

}
  1. 添加状态机
const PENDING = 'pending'
const FULFILLED  = 'fulfilled'
const REJECTED = 'rejected'

function MyPromise(fn){
    let self = this;
    self.state = PENDING;

    function resolve(data){
        if(self.state === PENDING){
            self.state = FULFILLED;
        }
    }

    function reject(data){
        if(self.state === PENDING){
            self.state = REJECTED
        }
    }

    try{
        fn(resolve,reject)
    }catch(e){
        reject(e)
    }
}
  1. then()
const PENDING = 'pending'
const FULFILLED  = 'fulfilled'
const REJECTED = 'rejected'

function MyPromise(fn){
    let self = this;
    self.state = PENDING;
    self.value  =  null;
    self.reason = null;

    function resolve(data){
        if(self.state === PENDING){
            self.state = FULFILLED;
            self.value = data
        }
    }

    function reject(data){
        if(self.state === PENDING){
            self.state = REJECTED
            self.reason =  data
        }
    }

    try{
        fn(resolve,reject)
    }catch(e){
        reject(e)
    }
}

MyPromise.prototype.then =function(onFulfilled,onRejected){
    let self = this
    if(self.state === FULFILLED){
        onFulfilled(self.value)
    }
    if(self.state  === REJECTED){
        onRejected(self.reason)
    }
}

  1. 加入异步调用(上述同步调用没问题,异步调用,then 方法很可能在异步调用结果前执行)
const PENDING = 'pending'
const FULFILLED  = 'fulfilled'
const REJECTED = 'rejected'

function MyPromise(fn){
    let self = this;
    self.state = PENDING;
    self.value  =  null;
    self.reason = null;
    self.onFulfilledCallback = []
    self.onRejectedCallback = []

    function resolve(data){
        if(self.state === PENDING){
            self.state = FULFILLED;
            self.value = data
            self.onFulfilledCallback.forEach(function(callback){
                callback()
            })
        }
    }

    function reject(data){
        if(self.state === PENDING){
            self.state = REJECTED
            self.reason =  data
            self.onRejectedCallback.forEach(function(callback){
                callback()
            })
        }
    }

    try{
        fn(resolve,reject)
    }catch(e){
        reject(e)
    }
}

MyPromise.prototype.then =function(onFulfilled,onRejected){
    let self = this

    if(self.state === PENDING){//异步先加入数组,resolve或reject时执行
        self.onFulfilledCallback.push(()=>{
          onFulfilled(self.value)
      })
         self.onRejectedCallback.push(()=>{
          onFulfilled(self.reason)
      })
    }

    if(self.state === FULFILLED){//同步直接执行
      onFulfilled(self.value)
    }
    if(self.state  === REJECTED){
         onFulfilled(self.reason)
    }
}
  1. then()方法返回 promise,并且返回的 promise,会执行 resolve,resolve 时的值为 then 中 onfulfilled 或 onRejected 时返回的值
MyPromise.prototype.then = function(onFulfilled,onRejected){
    let self = this
    let promise2 = null
    promise2  = new MyPromise(function(resolve,reject){
        if(self.state === PENDING){
            self.OnFulfilledCallback.push(()=>{
               try{
                   let value = onFulfilled(self.data)
                   self.resolvePromise(promise2,value,resolve,reject)
               }catch(e){
                   reject(e)
               }
            })

              self.onRejectedCallback.push(()=>{
               try{
                   let value = onRejected(self.reason)
                   self.resolvePromise(promise2,value,resolve,reject)
               }catch(e){
                   reject(e)
               }
            })
        }

        if(self.state === FULFILLED){
           try{
               let value = onFulfilled(self.value)
                self.resolvePromise(promise2,value,resolve,reject)
           }
           catch(e){
               reject(e)
           }
        }

        if(self.state === REJECTED){
            try{
                let value = onRejected(self.reason)
                self.resolve(promise2,value,resolve,reject)
            }catch(e){
                reject(e)
            }
        }
    })

    return promise2;
}

//onFulfilled或onRejected可能返回promise类型或基本类型值,这里统一处理
//根据PromiseA+中规范来实现[[Resolve]](promise, x)
MyPromise.prototype.resolvePromise = function(promise2,value,resolve,reject){
     let self = this;
     let called = false //防止多次调用
     if(promise2 === value){
        return reject(new TypeError('循环引用'))
     }
    if (x !== null && (Object.prototype.toString.call(x) === '[object Object]' || Object.prototype.toString.call(x) === '[object Function]')) {
    // x是对象或者函数
      try{
          let then = x.then;
          if(typeof then === 'function'){
            then.call(value,(fulfilled)=>{
        // 别人的Promise的then方法可能设置了getter等,使用called防止多次调用then方法
          if (called) return ;
          called = true;
             slef.resolvePromise(promise2,fulfilled,resolve,reject)
            },(rejected)=>{
                if (called) return ;
          called = true;
          reject(rejected)
            })
          }else{
              resolve(value)
          }
      }
      catch(e){
          if(called) return;
          called = true;
          reject(e)
      }
    }
    else{//普通数据直接resolve
        resolve(value)
    }
}
  1. 让then()方法的回调函数总是异步调用
MyPromise.prototype.then = function(onFulfilled,onRejected){
    let self  = this;
    let promise2 = null;
    promise2 = new MyPromise(function(resolve,reject){
        if(self.state === PENDING){
            self.onFulfilledCallback.push(()=>{
                setTimeout(()=>{
                     try{
                    let x = onFulfilled(self.value)
                    self.resolvePromise(promise2,x,resolve,reject)
                }catch(e){
                    reject(e)
                }
                },0)
            })
             self.onRejectedCallback.push(()=>{
                  setTimeout(()=>{
                      try{
                    let x = onRejected(self.value)
                    self.resolvePromise(promise2,x,resolve,reject)
                }catch(e){
                    reject(e)
                }
                },0)
              
            })
        }

        if(self.state === FULFILLED){
             setTimeout(() => {
             try{
                    let x = onFulfilled(self.value)
                    self.resolvePromise(promise2,x,resolve,reject)
                }catch(e){
                    reject(e)
                }
             },0)
        }

        if(self.state === REJECTED){
              setTimeout(() => {
            try{
                    let x = onRejected(self.value)
                    self.resolvePromise(promise2,x,resolve,reject)
                }catch(e){
                    reject(e)
                } },0)
        }
    })

    return promise2
}
  1. catch()方法
    then()中onrejected方法可以不传递,不传递如何执行then方法后如何将promise中reject中对象传给catch?
    因为then方法中方法有默认值
MyPromise.prototype.then =function(onFulfilled,onRejected){
   onFulfilled=  onFulfilled !== null? onFulfilled: (data)=>{return data}
    onRejected=  onRejected !== null? onRejected: (data)=>{throw data}
}
MyPromise.prototype.catch = function(onRejected){
    let self = this;
    self.then(null,onRejected)
}
  1. finally()
    无论是什么状态,最后都会执行finally()方法
MyPromise.prototype.finally = function(fn){
    return this.then((value)=>{
        fn()
        return value
    },(reason)=>{
        fn()
        throw reason
    })
}
  1. done()
    done方法作为Promise链式调用的最后一步,用来向全局抛出没有被Promise内部捕获的错误,并且不再返回一个Promise
    MyPromise.prototype.done = function(){
    this.catch((reason)=>{
    throw reason
    })
    }

  2. all()

MyPromise.all = function(arr){
    return new MyPromise((resolve,reject)=>{
       arr.forEach((promise,index)=>{
           promise.then((value)=>{
               result[index] = value
               if(result.length === arr.length){
                   resolve(result)
               }
           },reject)
       })
    })
}
  1. race()
MyPromise.race = function(arr){
  return new MyPromise((resolve,reject)=>{
      arr.forEach((promise)=>{
          promise.then(resolve,reject)
      })
  })
}
  1. resolve
MyPromise.resolve = function (value){
    let promise
    promise = new MyPromise((resolve,reject)=>{
        this.prototype.resolvePromise(promise,value,resolve,reject)
    })
    return promise
  1. reject
MyPromise.reject = function(value){
    return new MyPromise((resolve,reject)=>{
        reject(value)
    })
}

参考文档

  1. 从0到1实现Promise

你可能感兴趣的:(菜鸡啄食——JS,javascript,前端,typescript,es6,promise)