美文网首页
手写promise

手写promise

作者: Mr无愧于心 | 来源:发表于2019-01-07 17:03 被阅读0次

建议请先阅读

原理1原理2原理3

function Promise(executor){
  let self=this;
  self.status='pending'//给promise设置初始状态pending;
  self.onfulfilledList=[];//用来订阅then中成功的回调onfulfilled
  self.onrejectedList=[];//用来订阅then中失败的回调onrejected
  try{
    executor(resolve,reject);//执行传入promise的这个回调函数executor,
    //并传入resolve,reject这两个函数作为实参。
  }catch(err){
    reject(err);//如果执行executor抛出错误,那就进入失败状态。
  }
 
    //定义resolve reject这两个函数
  function resolve(value){//接受一个参数value
    if(self.status=='pending'){
    //只有当promise的状态是pending时调用resolve才会进行状态的改变
      self.status='fulfilled';//调用resolve表示成功,状态变为fulfilled
      self.value=value//将值挂载到promise上,用于then的onfulfilled中拿到value;
      self.onfulfilledList.forEach(function(fn){//逐个执行成功态then中添加的回调
        fn();          
      })
    }
  }
  function reject(reason){
    if(self.status=='pending'){
      self.status='rejected'//调用reject表示失败,状态变为rejected
      self.reason=reason//把失败的原因挂载到promise上,方便then的onrejected拿到reason
       self.onrejectedList.forEach(function(fn){//逐个执行失败态then中添加的回调
        fn();          
      })
    }
  }
}
Promise.prototype.then=function(onfulfilled,onrejected){
    let self=this;
    let promise2=new Promise(function(resolve,reject){//返回这个promise对象
        //这个新的对象需要做的有判断当前的状态
        //判断then的onfulfilled的参数类型,onrejeced中拿到的参数的类型
        //如果then中的参数不是一个函数的话,那么promise中的value或reason就继续向下一个then传递
        //如果then的回调中返回的是一个普通对象那么就继续向下一个then传递
        //如果返回的是一个promise对象那么这个promise对象就作为下一个then的promise使用覆盖promise2;
        if(typeof onfulfilled !=='function'){//如果不是函数就将value向下传递数据
            onfulfilled=function(value){
                return value;
            }
        }
        if(typeof onrejected!=='function'){//如果不是函数就将reason向下传递数据
            onrejected=function(reason){
                return reason;
            }
        }

        if(self.status=='fulfilled'){//成功状态
            setTimeout(function(){//计时器异步的另一个作用是能让promise2对象能在promise2中正确引用
                try{
                    let x=onfulfilled(self.value);//拿到onfulfilled的返回值
                    resolvePromise(promise2,x,resolve,reject);//这个函数用来判断以上then的返回值,以处理then向下传递的状态走resolve函数还是reject函数
                }catch(e){
                    //抛出错误就返回错误
                    reject(e);
                }

            },0);
        }
        if(self.status=='rejected'){//失败状态
            setTimeout(function(){
                try{
                    let x=onrejected(self.reason);//拿到onrejected的返回值
                    resolvePromise(promise2,x,resolve,reject);
                }catch(e){
                    //抛出错误就返回错误
                    reject(e);
                }
            },0)
        }
        if(self.status=='pending'){//等待状态
            self.onfulfilledList.push(function(){
                setTimeout(function(){//计时器异步的另一个作用是能让promise2对象能在promise2中正确引用
                    try{
                        let x = onfulfilled(self.value);//拿到onfulfilled的返回值
                        resolvePromise(promise2, x, resolve, reject);
                    }catch(e){
                        reject(e)
                    }
                },0)
            })
            self.onrejectedList.push(function(){
                setTimeout(function(){
                    try{
                        let x = onrejected(self.reason);//拿到onrejected的返回值
                        resolvePromise(promise2, x, resolve, reject);
                    }catch(e){
                        reject(e);
                    }
                },0)
            })
        }
    })
    return promise2;
}

//处理then回调中x返回值的状态
function resolvePromise(promise2,x,resolve,reject){
    if(promise2 === x){//如果then回调中返回的x和promise2是一个就会陷入死循环
        return reject(new Error('死循环'))
    }
    let changeFlag;//用来做状态标识,如果状态改变后,就不再改变
    if((x!=null)&&(typeof x=='object'||typeof x=='function')){//判断x的类型函数或对象
        try{
            let then = x.then;
            //之所以用then取值而不使用x.then的原因是:避免多次取值造成不必要的错误(代码更加严谨)
            //Object.definedProperty(x,then,{get(){处理取值结果,改变不同的值}});
            if(typeof then == 'function'){//说明x有then方法
                then.call(x,function(y){
                    //resolve(value)不是应该向下传递应该继续判断下一个then的返回值类型
                    if(!changeFlag){changeFlag=true}else{return}
                    resolvePromise(x,y,resolve,reject)//递归判断
                    //避免返回的promise中依然返回的是promise,把所有嵌套的promise都执行,直到返回普通值
                },function(reason){
                    if(!changeFlag){changeFlag=true}else{return}
                    reject(reason);
                })
            }else{//不是一个promise,是个普通的对象,数据向下传递
                resolve(x)
            }
        }catch(e){
            if(!changeFlag){changeFlag=true}else{return}
            reject(e)
        }
    }else{//说明返回的是普通值,向下传递
        resolve(x)
    }
};
Promise.prototype.catch=function(errCallback){
  return this.then(null,errCallback);
}
Promise.prototype.finally=function(callback){
  return this.then(function(data){
    callback()
    return data
  },function(reason){
    callback();
    return reason;
  })
}
Promise.resolve=function(data){
  return new Promise(function(resolve,reject){
    resolve(data);    
  })
}
Promise.reject=function(data){
  return new Promise(function(resolve,reject){
    reject(data);    
  })
}
Promise.all=function(promiseList){
  return new Promise(function (resolve, reject) {
     let arr=[],i=0;//纪录向下传递的数组和总共执行的次数
     promiseList.forEach(function(curPromise,index){
        if(typeof curPromise == 'object'&&curPromise.then){//说明是promise
           curPromise.then(function(data){
              arr[index]=data;
              i++;
              if(i==promiseList.length){//数组执行结束
                 resolve(arr)
              }
           })
        }else{
          arr[index]=curPromise;
          i++;
          if(i==promiseList.length){//数组执行结束
              resolve(arr)
          }
        }
    })
  })
}
Promise.race = function (promises) {
  return new Promise(function (r, reject) {
    for (let i = 0; i < promises.length; i++) {
      if(typeof  promises[i]=== 'object' &&  promises[i].then){
        promises[i].then(r,reject);
      }else{
        r(promises[i])
      }
    }
  })
}
Promise.deferred = Promise.defer = function () {
  let dfd = {}
  dfd.promise = new Promise(function (resolve, reject) {
    dfd.resolve = resolve;
    dfd.reject = reject;
  });
  return dfd;
}

相关文章

  • 手写Promise

    手写 Promise 我们会通过手写一个符合 Promise/A+ 规范的 Promise 来深入理解它,并且手写...

  • 手写 Promise 系列 --- 3

    在前两篇(手写 Promise 系列 --- 1)和(手写 Promise 系列 ---2) 中,达成了3个目标 ...

  • 手写Promise

    $ 正常的promise用法   $ 手写的Promise   # 测试可行性

  • 手写promise

    手写promise 带大家手写一个 promis。在手写之前我会先简单介绍一下为什么要使用promise、prom...

  • 纯手写实现自己的nodejs promise 库

    纯手写实现自己的nodejs promise 库什么是Promise?promise 链Async/Await后续...

  • 手写基础 promise

    1. 前言 玩下吧 手写 promise,看看能写成啥样 2. promise 基础结构 3. 手写`promi...

  • 手写 Promise

    一、Promise 是一个异步操作返回的对象,用来传递异步操作的消息。 Promise 介绍和使用详见: 认识并使...

  • 手写Promise

  • 手写Promise

    Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。 这篇博客有关于P...

  • 手写promise

    本章节纯粹是对promise手写实现。如果不了解promise自行了解再来学习本章知识。promise初体验首先,...

网友评论

      本文标题:手写promise

      本文链接:https://www.haomeiwen.com/subject/eezurqtx.html