Promise手写原理

  1. promise 就是一个类,在执行这个类的时候,需要传递一个执行器,执行器会立即执行
  2. promise 中有3种状态,分别为成功(fulfilled),失败(rejected)和进行中(pending) pedding->fulfilled pedding->rejected
  3. resolve 和reject函数是来更新状态
  4. resolve:fulfilled reject: rejected
  5. then方法是判断状态,如果状态是成功则调用成功回调函数,如果状态是失败则调用失败回调函数。then方法是被定义在原型对象中
  6. then成功回调有一个参数,表示成功之后的值,then失败回调有一个参数,表示失败后的原因
  7. then方法是可以被调用的,后面的then方法的回调函数拿到值的是上一个then方法的回调函数返回值

思考Promise写法注意点

  1. 写主体逻辑代码,第一步先写出一个类,之后再一步一步构造
  2. 之后考虑异步调用resolve,传入的是异步代码。所以将成功失败函数存起来,判断是否需要异步再次调用
  3. 当有多个then调用的时候,我们就需要考虑使用数组
  4. 当then,有多层嵌套的时候。需要处理then的链式调用,如何把then的返回值返回到下一个then中,需要返回promisee对象.
  5. 所以需要封装promise,实现链式调用
  6. 如果出现循环调用promise的时候,
  7. 错误处理,会在构造器中使用try.catch,在then成功回调函数里面也使用try.catch
  8. Promise.all() 写静态文件函数all()来处理
  9. Promise.resolve() 直接传参数,进行返回判断是promise对象还是非promise对象。是对象的化,直接返回,不是的化,生产一个对象,包裹返回
  10. Primise.finally() 不管promise执行是否成功还是失败,finally()依然会执行一次。可以通过then的方法获取到这个promise的最终结果
  11. finally()不是类的方法,是原型对象上的方法。
  12. Primise.catch() 是原型对象的方法。如果then没有打印错误,catch()里需要捕获
const  PENDING = 'pending'; // 等待
const  FULFILLED = 'filfull ed'; // 成功
const  REJECTED = 'rejected'; // 等待

class MyPromise {
  constructor(executor){
    //因为在类里面所以需要this.才能访问
    try{
     executor(this.resolve,this.reject)
    }catch(e){
      this.reject(e)
    }
  };
  //Promise 状态
  status = PENDING;
  // //成功之后的值
  value = undefined;
  //失败之后的原因
  reason = undefined;
  //成功的回调
  successCallback = []
  //失败的回调
  failCallback = []
  resolve = value =>{
    //如果状态不是等待,就阻止程序想下执行
    if(this.status !== PENDING) return
    //将状态更改为成功
    this.status = FULFILLED;
    //保存成功的值
    this.value = value
    //判断成功回调是否存在 shift()删除其中的第一个值,获取到,并且返回剩下的数组
    while(this.successCallback.length) this.successCallback.shift()()
  }; 
  reject = err =>{
    //如果状态不是等待,就阻止程序想下执行
    if(this.status !== PENDING) return
     //将状态更改为失败
     this.status = REJECTED; 
     //保存失败的原因
     this.reason = err
     //判断失败回调是否存在 shift()删除其中的第一个值,获取到,并且返回剩下的数组
     while(this.failCallback.length) this.failCallback.shift()()
  } 
  then(successCallback,failCallback){
    successCallback=  successCallback ? successCallback : value=>value;
    failCallback=  failCallback ? failCallback : reson=>{ throw(reson)};
    let promise2 = new MyPromise((resolve,reject)=>{
      if(this.status === FULFILLED){
        //此处是不能获取到promise2的,只有new MyPromise执行之后才会获取到。我们现在是在new MyPromise过程中
        //(所以将promise2变成异步代码使用setTimeout让其改变成异步代码,让所有代码执行完成,promise2就有了,然后我们去执行函数内部的代码)
        setTimeout(()=>{
          try{
            //判断X的值是普通函数还是Promise对象
            //如果是普通值,直接调用resolve
            //如果是primise对象,查看promise对象返回的结果 
            //再根据promise对象返回的结果,决定调用resolve还是reject
            let x = successCallback(this.value)
            //判断 promise2 和X 是否相等,如果相等,就等于返回了自己
            resolvePrimise(promise2 ,x,resolve,reject)
          }catch(e){
            reject(e)
          }
        },0)
      }else if(this.status === REJECTED){
        //此处是不能获取到promise2的,只有new MyPromise执行之后才会获取到。我们现在是在new MyPromise过程中
        //(所以将promise2变成异步代码使用setTimeout让其改变成异步代码,让所有代码执行完成,promise2就有了,然后我们去执行函数内部的代码)
        setTimeout(()=>{
          try{
            //判断X的值是普通函数还是Promise对象
            //如果是普通值,直接调用resolve
            //如果是primise对象,查看promise对象返回的结果 
            //再根据promise对象返回的结果,决定调用resolve还是reject
            let x = failCallback(this.reason)
            // 判断 promise2 和X 是否相等,如果相等,就等于返回了自己
            resolvePrimise(promise2 ,x,resolve,reject)
          }catch(e){
            reject(e)
          }
        },0)
      }else{
        //等待状态
        //将成功回调和失败回调存起来
        this.successCallback.push(()=>{
          setTimeout(()=>{
            try{
              //判断X的值是普通函数还是Promise对象
              //如果是普通值,直接调用resolve
              //如果是primise对象,查看promise对象返回的结果 
              //再根据promise对象返回的结果,决定调用resolve还是reject
              let x = successCallback(this.value)
              // 判断 promise2 和X 是否相等,如果相等,就等于返回了自己
              resolvePrimise(promise2 ,x,resolve,reject)
            }catch(e){
              reject(e)
            }
          },0)
        })
        this.failCallback.push(()=>{
          setTimeout(()=>{
            try{
              //判断X的值是普通函数还是Promise对象
              //如果是普通值,直接调用resolve
              //如果是primise对象,查看promise对象返回的结果 
              //再根据promise对象返回的结果,决定调用resolve还是reject
              let x = failCallback(this.reason)
              // 判断 promise2 和X 是否相等,如果相等,就等于返回了自己
              resolvePrimise(promise2 ,x,resolve,reject)
            }catch(e){
              reject(e)
            }
          },0)
        })
      }
    })
    return promise2
  }
  finaally(callback){
    //通过调用then的方法,我们可以得到成功还是失败。无论什么情况都可以调用
    return this.then(value =>{
      return MyPromise.resolve(callback()).then(()=> value)
    },reject=>{
      return MyPromise.resolve(callback()).then(()=>  {throw reject})
    })
  }  
  catch(failCallback){
    return this.then(undefined,failCallback)
  }
  //声明all是一个静态方法
  static all(array){
    let result = [];
    let index = 0
    return new MyPromise((resolve,reject)=>{
      function addData(key,value){
        result[key] = value;
        index++
        if(index === array.length){
          resolve(result)
        }
      }
      for(let i= 0;i<array.length;i++){
        let current = array[i];
        if(current instanceof MyPromise){
          //promise对象
          current.then(value =>addData(i,value) ,reson =>{
            reject(reson)
          })
        }else{
          //普通值
          addData(i,array[i]);
        }
      }
    })
  }
  static resolve(val){
    if(val instanceof MyPromise) val
    return new MyPromise(resolve=>resolve(val))
  }
}

//判断是普通值还是Mypromisee
function resolvePrimise(promise2,x,resolve,reject){
*  *if(promise2 === x){
    // 使用return,阻止下面代码执行了
    return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
  }
  //x是否属于Mypromisee类下面的实例, 
  if(x instanceof MyPromise){
    //primose
    //x.then(value=>resolve(value),err => reject(err))
    x.then(resolve,reject)
  }else{
    //普通值
    resolve(x) 
  }
   
}
复制代码

这是主体代码 第一步,都是基于第一步进行改编。结合思考Promise写法注意点


const PENDING = 'peding'
const REJECTED = 'rejected'
const FILFULLED = 'filfulled'
class MyPromise{
  constructor(executor){
    executor(this.resolve,this.reject)
  }
  status = PENDING
  value = undefined // 成功的数据
  filed = undefined // 失败的数据

  resolve = value =>{
    if(this.status !== PENDING) return
    this.status = FILFULLED
    this.value = value
  }

  reject = filed =>{
    if(this.status !== PENDING) return
    this.status = REJECTED
    this.filed = filed
  }

  then(successCallback,failCallback){
    if(this.status == FILFULLED){
      successCallback(this.value)
    }else if(this.status == REJECTED){
      failCallback(this.filed)
    }
  }
}

let b=  new MyPromise((resolve,reject)=>{
  // resolve('成功')
 reject('shibao')
})

b.then(res=>{
  console.log(res)
},err=>{
  console.log(err)
})
复制代码

以下是代码测试区域,仅供参考,可以自己实现测试方法

let primise = new MyPromise((resolve,reject)=>{
  // throw new Error('executor Error')
 // resolve('成功')
  setTimeout(()=>{
    resolve('成功1')
  },2000)
  // resolve('成功')

  // reject('失败')
})

let primise1  = new MyPromise((resolve,reject)=>{
  // resolve('p3 成功')
  // setTimeout(()=>{
  //   resolve('成功1')
  // },2000)
  reject('p2 失败')
})


// a.then((resolve)=>{
//   console.log(resolve)
//   //throw new Error('then Error')
//   return 'aaa';
// },err=>{ 
//   console.log(err)
//   return 10000
// }).then((resolve)=>{
//   console.log(resolve)
// })

// primise1.finaally(()=>{
//   console.log('finaally')
//   return primise
// }).then(value=>{
//   console.log(value)
// },resone=>{
//   console.log(resone)
// })

primise1.then(value=>console.log(value))
  .catch(reasonn=> console.log(reasonn))

// primise.then().then().then().then(value=>console.log(value),err=>{
//   console.log(err)
// })

// MyPromise.all(['a','b',primise,primise1,'c']).then(res=>console.log(res),rej=>console.log(rej))
// MyPromise.resolve(100).then(value=>console.log(value))
// MyPromise.resolve(primise).then(value=>console.log(value))

//此时promise被循环调用
// var cc = new Promise((res,rej)=>{
//   res(100)
// })

// let p = cc.then((res)=>{
//   console.log(res)
//   return p 
// })

// p.then(()=>{},(err)=>{
//   console.log(err)
// })
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享