教你一步一步手动实现Promise(附源码)

实现Promise

第一步:定义构造,接受一个函数作为参数,这个函数有两个参数,这两个参数都是函数,分别是resolve和reject。resolve作用是把状态从pending改变为fulfilled,异步操作成功后,把值传递出去。reject作用是把状态从pending改变为rejected,异步操作失败后,把报错信息传递出去,需要注意的是,它有三种状态,分别是pending(进行中),fulfilled(已成功),rejected(已失败),状态一旦凝固,将不可改变

const PENDING = 'pending';//进行中
const FULFILLED = 'fulfilled';//成功
const REJECTED = 'rejected';//失败

/*
 *promsie构造
 *@params executor {funciton} 接收一个函数,为了接受暴漏的resolve和reject
 */
function MyPromise(executor) {
    let self = this;
    self.status = PENDING;
    self.fulfilledValue = undefined;//状态置为fulfilled时候,传递的值
    self.rejectValue = undefined;//状态置为rejected时候,传递的值

    /*
     *成功
     *@params value {引用类型|基本类型} 接受状态置为成功,传递的值
     */
    function resolve(value) {
        if (self.status === PENDING) {
            self.status = FULFILLED;
            self.fulfilledValue = value;
        }
    }
    /*
     *失败
     *@params value {引用类型|基本类型} 接受状态置为失败,传递的值
     */
    function reject(value) {
        if (self.status === PENDING) {
            self.status = REJECTED;
            self.rejectValue = value;
        }
    }

    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

 第二步,定义原型上的then方法,then方法提供两个回调函数,一个是成功的回调,一个是失败的回调,这里需要注意,接收的必须是必须是函数。

/*
 *then,成功或失败的回调
 *@params onFulfilled 成功的回调
 *@params onRejected  失败的回调
 */
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    onFulfilled =typeof onFulfilled === "function"? onFulfilled: function(param) {return param;};
    onRejected =typeof onRejected === "function"? onRejected: function(e) {throw e;}
    switch (self.status) {
        //状态为成功
        case FULFILLED:
            onFulfilled(self.fulfilledValue);
            break;
        //状态为失败
        case REJECTED:
            onRejected(self.rejectValue);
            break;
    }
}

截至目前,promise的简单框架已经搭好了,咱们现在也测试一下。

   var promise=new MyPromise(function(resolve,reject){
            resolve("promise")
        })
        promise.then((data)=>{
            console.log(data)//promsie
        })

结果表明成功了,但是我们再来看一下例子:

        var promise=new MyPromise(function(resolve,reject){
            // setTimeout(()=>{
                resolve("promise")
            // })
        })
        promise.then((data)=>{
            console.log(data)
        })
        console.log("1111")

看下控制台结果:

哇,promise阻塞了同步任务的执行,这显然违背了promise的初衷,所以,成功和失败的回调应该是异步的。

/*
 *then,成功或失败的回调
 *@params onFulfilled 成功的回调
 *@params onRejected  失败的回调
 */
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    onFulfilled =typeof onFulfilled === "function"? onFulfilled: function(param) {return param;};
    onRejected =typeof onRejected === "function"? onRejected: function(e) {throw e;}
    switch (self.status) {
        //状态为成功
        case FULFILLED:
            setTimeout(funciton(){
                onFulfilled(self.fulfilledValue);
            })
            break;
        //状态为失败
        case REJECTED:
            setTimeout(funciton(){
                onRejected(self.rejectValue);
            })
            break;
    }
}

好了,这里就成功了解决了阻塞的问题,但是这里还有个问题,相信大家都已经猜出来了,就是resolve是异步的情况下,在调用then的时候,状态还没有置为fulfilled或者rejected,那么这时候是没有可执行的代码,所以呢,我们就需要提供状态为pending时的逻辑,解决方案就是,提供两个数组,分别用来存储成功和失败的回调,等异步队列有结果返回时,就去循环所存的回调。

/*
 *promsie构造
 *@params executor {funciton} 接收一个函数,为了接受暴漏的resolve和reject
 */
function MyPromise(executor) {
    let self = this;
    self.status = PENDING;
    self.onFullfilledArray = [];//成功的回调数组
    self.onRejectedArray = []; //失败的回调数组
    self.fulfilledValue = undefined;//状态置为fulfilled时候,传递的值
    self.rejectValue = undefined;//状态置为rejected时候,传递的值

    /*
     *成功
     *@params value {引用类型|基本类型} 接受状态置为成功,传递的值
     */
    function resolve(value) {
        if (self.status === PENDING) {
            self.status = FULFILLED;
            self.fulfilledValue = value;
            for (let fn of self.onFullfilledArray) {
                fn()
            }
        }
    }
    /*
     *失败
     *@params value {引用类型|基本类型} 接受状态置为失败,传递的值
     */
    function reject(value) {
        if (self.status === PENDING) {
            self.status = REJECTED;
            self.rejectValue = value;
            for (let fn of self.onRejectedArray) {
                fn()
            }
        }
    }

    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}
/*
 *then,成功或失败的回调
 *@params onFulfilled 成功的回调
 *@params onRejected  失败的回调
 */
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (param) { return param; };
    onRejected = typeof onRejected === "function" ? onRejected : function (e) { throw e; }
    let promise2;
    switch (self.status) {
        //状态为进行中
        case PENDING:
            self.onFullfilledArray.push(function(){
                setTimeout(function(){
                    onFulfilled(self.fulfilledValue)
                })
            })
            self.onRejectedArray.push(function(){
                setTimeout(function(){
                    onRejected(self.fulfilledValue)
                })
            })

            break;
        //状态为成功
        case FULFILLED:
            setTimeout(function(){
                onFulfilled(self.fulfilledValue);
            })
            break;
        //状态为失败
        case REJECTED:
            setTimeout(function() {
                onRejected(self.rejectValue);
            })
            break;
    }
}

好了,截至目前基本的架构算是真正的解决,接下来,咱们就去完成它的精髓,就是实现then的链式调用,所以then必须返回一个崭新的promise。

/*
 *then,成功或失败的回调
 *@params onFulfilled 成功的回调
 *@params onRejected  失败的回调
 */
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (param) { return param; };
    onRejected = typeof onRejected === "function" ? onRejected : function (e) { throw e; }
    let promise2;
    switch (self.status) {
        //状态为进行中
        case PENDING:
            promise2 = new MyPromise(function (resolve, reject) {
                self.onFullfilledArray.push(function () {
                    setTimeout(function () {
                        onFulfilled(self.fulfilledValue)
                    })
                })
                self.onRejectedArray.push(function () {
                    setTimeout(function () {
                        onRejected(self.fulfilledValue)
                    })
                })
            })

            break;
        //状态为成功
        case FULFILLED:
            promise2 = new MyPromise(function (resolve, reject) {
                setTimeout(function () {
                    onFulfilled(self.fulfilledValue);
                })
            })

            break;
        //状态为失败
        case REJECTED:
           promise2 = new MyPromise(function (resolve, reject) {
                setTimeout(function () {
                    onRejected(self.rejectValue);
                })
            })
            break;
    }
    return promise2
}

好了,目前已经可以链式调用了,但是,目前是无法进行值的传递的,接下来咱们就来实现值的传值,then的返回值有三种情况

  1. 如果x为对象或者函数
    (1)把x.then赋给then
    (2)如果取x.then值的时候抛出错误e,则reject()
    (3)如果x不为对象或函数,则resolve(x);
    (4)如果x时函数,则以x作为函数作用域this调用之,同样返回成功回调和失败回调,如果成功,则运行[[Resolve]](promise, y)
  2. x为新的promsie实例
    如果x为promsie,则使 promsie接受x的状态 
  3. 直接resolve
/*
 *成功或失败的回调
 *@params onFulfilled 成功的回调
 *@params onRejected  失败的回调
 */
/*
 *then,成功或失败的回调
 *@params onFulfilled 成功的回调
 *@params onRejected  失败的回调
 */
MyPromise.prototype.then = function (onFulfilled, onRejected) {
    let self = this;
    onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (param) { return param; };
    onRejected = typeof onRejected === "function" ? onRejected : function (e) { throw e; }
    let promise2;
    switch (self.status) {
        //状态为进行中
        case PENDING:
            promise2 = new MyPromise(function (resolve, reject) {
                self.onFullfilledArray.push(function () {
                    setTimeout(function () {
                        try{
                            let results=onFulfilled(self.fulfilledValue);
                            resolvePromise(promise2,results,resolve,reject)
                        }catch(e){
                            reject(e)
                        }
                    })
                })
                self.onRejectedArray.push(function () {
                    setTimeout(function () {
                        try{
                            let results=onRejected(self.rejectValue);
                            resolvePromise(promise2,results,resolve,reject)
                        }catch(e){
                            reject(e)
                        }
                    })
                })
            })

            break;
        //状态为成功
        case FULFILLED:
            promise2 = new MyPromise(function (resolve, reject) {
                setTimeout(function () {
                    try{
                        let results=onFulfilled(self.fulfilledValue);
                        resolvePromise(promise2,results,resolve,reject)
                    }catch(e){
                        reject(e)
                    }
                    
                })
            })
            break;
        //状态为失败
        case REJECTED:
           promise2 = new MyPromise(function (resolve, reject) {
                setTimeout(function () {
                    try{
                        let results=onRejected(self.rejectValue);
                        resolvePromise(promise2,results,resolve,reject)
                    }catch(e){
                        reject(e)
                    }
                })
            })
            break;
    }
    return promise2
}
/*
 *处理then返回值
 *@params promise2 新创建的promise
 *@params result then的返回值
 *@params resolve 成功
 *@params reject 失败
 **/
function resolvePromise(promise2, result, resolve, reject) {
    if (promise2 === result) { //不支持then()将自己创建的Promise进行返回
        return new TypeError("Chaining cycle")
    } else if (result instanceof MyPromise) {
    // 如果 result 为 Promise ,则使 promise 接受 result 的状态
    // 如果 result 处于等待态, promise 需保持为等待态直至 result 被执行或拒绝
    if (result.status === PENDING) {
      result.then(
        y => {
          resolvePromise(promise2, y, resolve, reject)
        },
        reason => {
          reject(reason)
        }
      )
    } else {
      // 如果 result 处于执行态,用相同的值执行 promise
      // 如果 result 处于拒绝态,用相同的据因拒绝 promise
      result.then(resolve, reject)
    }
  } else if (result && (typeof result === "object" || typeof result === "function")) {
        let isUsed=false;
        let then=result.then;
        if (typeof then === "function") {
            then.call(result,function(data){
                resolvePromise(promise2,data,resolve,reject)
            },function(e){
                reject(e)
            })
        }else{
            resolve(result)
        }
    } else {
        resolve(result)
    }
}

OK,接下来我们来测试一下,先测试下不是数组也不是对象的。

        var promise=new MyPromise(function(resolve,reject){
            setTimeout(()=>{
                resolve("promise")
            })
        })
        promise.then((data)=>{
            console.log(data)
            return "不是对象也不是数组"
        }).then((data)=>{
            console.log(data);
            return function add(){
                console.log("函数")
            }
        }).then((data)=>{
            console.log(data)
        })

完美!!完全正确,接下来测试下thenable的。

        var promise=new MyPromise(function(resolve,reject){
            setTimeout(()=>{
                resolve("promise")
            })
        })
        promise.then((data)=>{
            console.log(data)
            return {
                then:function(resolve,reject){
                    resolve("thenable")
                }
            }
        }).then((data)=>{
            console.log(data)
        })

nice!!!也正确,接下在测试一下返回值为promsie的

        var promise=new MyPromise(function(resolve,reject){
            setTimeout(()=>{
                resolve("promise")
            })
        })
        promise.then((data)=>{
            console.log(data);
            return new MyPromise((resolve,reject)=>{
                resolve("返回Promise")
            })
        }).then((data)=>{
            console.log(data)
        })

大功告成!!!!!

全部源码

es5写法:

!function(win){
    const PENDING = 'pending';//进行中
    const FULFILLED = 'fulfilled';//成功
    const REJECTED = 'rejected';//失败
    /*
     *promsie构造
     *@params executor {funciton} 接收一个函数,为了接受暴漏的resolve和reject
     */
    function MyPromise(executor) {
        let self = this;
        self.status = PENDING;
        self.onFullfilledArray = [];//成功的回调数组
        self.onRejectedArray = []; //失败的回调数组
        self.fulfilledValue = undefined;//状态置为fulfilled时候,传递的值
        self.rejectValue = undefined;//状态置为rejected时候,传递的值
    
        /*
         *成功
         *@params value {引用类型|基本类型} 接受状态置为成功,传递的值
         */
        function resolve(value) {
            if (self.status === PENDING) {
                self.status = FULFILLED;
                self.fulfilledValue = value;
                for (let fn of self.onFullfilledArray) {
                    fn()
                }
            }
        }
        /*
         *失败
         *@params value {引用类型|基本类型} 接受状态置为失败,传递的值
         */
        function reject(value) {
            if (self.status === PENDING) {
                self.status = REJECTED;
                self.rejectValue = value;
                for (let fn of self.onRejectedArray) {
                    fn()
                }
            }
        }
    
        try {
            executor(resolve, reject);
        } catch (e) {
            reject(e);
        }
    }
    /*
     *成功或失败的回调
     *@params onFulfilled 成功的回调
     *@params onRejected  失败的回调
     */
    /*
     *then,成功或失败的回调
     *@params onFulfilled 成功的回调
     *@params onRejected  失败的回调
     */
    MyPromise.prototype.then = function (onFulfilled, onRejected) {
        let self = this;
        onFulfilled = typeof onFulfilled === "function" ? onFulfilled : function (param) { return param; };
        onRejected = typeof onRejected === "function" ? onRejected : function (e) { throw e; }
        let promise2;
        switch (self.status) {
            //状态为进行中
            case PENDING:
                promise2 = new MyPromise(function (resolve, reject) {
                    self.onFullfilledArray.push(function () {
                        setTimeout(function () {
                            try{
                                let results=onFulfilled(self.fulfilledValue);
                                resolvePromise(promise2,results,resolve,reject)
                            }catch(e){
                                reject(e)
                            }
                        })
                    })
                    self.onRejectedArray.push(function () {
                        setTimeout(function () {
                            try{
                                let results=onRejected(self.rejectValue);
                                resolvePromise(promise2,results,resolve,reject)
                            }catch(e){
                                reject(e)
                            }
                        })
                    })
                })
    
                break;
            //状态为成功
            case FULFILLED:
                promise2 = new MyPromise(function (resolve, reject) {
                    setTimeout(function () {
                        try{
                            let results=onFulfilled(self.fulfilledValue);
                            resolvePromise(promise2,results,resolve,reject)
                        }catch(e){
                            reject(e)
                        }
                        
                    })
                })
                break;
            //状态为失败
            case REJECTED:
               promise2 = new MyPromise(function (resolve, reject) {
                    setTimeout(function () {
                        try{
                            let results=onRejected(self.rejectValue);
                            resolvePromise(promise2,results,resolve,reject)
                        }catch(e){
                            reject(e)
                        }
                    })
                })
                break;
        }
        return promise2
    }
    /*
     *处理then返回值
     *@params promise2 新创建的promise
     *@params result then的返回值
     *@params resolve 成功
     *@params reject 失败
     **/
     function resolvePromise(promise2, result, resolve, reject) {
            if (promise2 === result) { //不支持then()将自己创建的Promise进行返回
                return new TypeError("Chaining cycle")
            } else if (result instanceof MyPromise) {
                // 如果 result 为 Promise ,则使 promise 接受 result 的状态
                // 如果 result 处于等待态, promise 需保持为等待态直至 result 被执行或拒绝
                if (result.status === PENDING) {
                    result.then(y => {
                        resolvePromise(promise2, y, resolve, reject)
                    },reason => {
                        reject(reason)
                    })
                } else {
                    // 如果 result 处于执行态,用相同的值执行 promise
                    // 如果 result 处于拒绝态,用相同的据因拒绝 promise
                    result.then(resolve, reject)
                }
            } else if (result && (typeof result === "object" || typeof result === "function")) {
                let isUsed=false;
                let then=result.then;
                if (typeof then === "function") {
                    then.call(result,function(data){
                        resolvePromise(promise2,data,resolve,reject)
                    },function(e){
                        reject(e)
                    })
                }else{
                    resolve(result)
                }
            } else {
                resolve(result)
            }
    }

    win.MyPromise=MyPromise
}(window)

es6写法

        (function(win){
          const PENDING = 'pending' // 进行中
          const FULFILLED = 'fulfilled' // 成功
          const REJECTED = 'rejected'// 失败
          let thenValue;
          /*
           * reslove
           */
          const resolve = function(value){
            if(this.promiseStatus===PENDING){
              this.promiseStatus = FULFILLED
              this.fulfilledValue = value
              for(let fn of this.fulfilledArr){
                fn(this.fulfilledValue)
              }
            }
          }
          /*
           * reject
           */
          const reject = function(value){
            if(this.promiseStatus===PENDING){
              this.promiseStatus = REJECTED
              this.rejectedValue = value
              for(let fn of this.rejectedArr){
                fn(this.rejectedValue)
              }
            }
          } 
          /*
           * then的返回值处理
           * des {
           * 1.对象或者函数
           * 2.新的promsie实例
           * 3.无返回值
           * }
           */
          const delFn = function(promise2,result,resolve,reject){
            if(promise2 === result){
              throw new TypeError ('Chaining cycle')
            } else if (result instanceof myPromise){
                if(result.status === PENDING) {
                    result.then((y)=>{
                        delFn(promise2,y,resolve,reject)
                    },(reson)=>{
                        reject(reason)
                    })
                }
            } else if(result && (typeof result === "object" || typeof result === "function")){
              
              let thenCalledOrThrow = false
              let then = result.then
              if (typeof then === 'function'){
                then.call(result,function(data){
                  if (thenCalledOrThrow) return
                  thenCalledOrThrow = true
                  delFn(promise2,data,resolve,reject)
                },function(e){
                  if (thenCalledOrThrow) return
                  thenCalledOrThrow = true
                  reject(e)
                })
              } else {
                if (thenCalledOrThrow) return
                thenCalledOrThrow = true
                resolve(result)
              }
            } else {
              if (thenCalledOrThrow) return
                thenCalledOrThrow = true 
              resolve(result)
            }
          }

          class myPromise {
            constructor(executor){
              this.promiseStatus = PENDING
              this.fulfilledValue = ''
              this.rejectedValue = ''
              this.fulfilledArr = [] // 成功回调,因为reslove可能会存在异步,所以需要存起来
              this.rejectedArr = [] // 失败回调,因为reject可能也会存在异步,所以需要存起来
              try {
                executor(resolve.bind(this), reject.bind(this))
              } catch (e) {
                reject.call(this,e);
              }
            }
            then(resloveFun,rejectFun){
              let promise2
              resloveFun = typeof resloveFun === "function" ? resloveFun : function (param) { return param; };
              rejectFun = typeof rejectFun === "function" ? rejectFun : function (e) { throw e; }
              switch (this.promiseStatus) {
                case PENDING:
                  promise2 = new myPromise ((resolve,reject)=>{
                    this.fulfilledArr.push(()=>{
                      setTimeout(()=>{
                        try {
                          thenValue = resloveFun(this.fulfilledValue)
                          delFn(promise2,thenValue,resolve,reject)
                        } catch (error) {
                          reject(error)
                        }
                      })
                    })
                    this.rejectedArr.push(()=>{
                      setTimeout(()=>{
                        try {
                          thenValue = rejectFun(this.rejectedValue)
                          delFn(promise2,thenValue,resolve,reject)
                        } catch (error) {
                          reject(error)
                        }
                      })
                    })
                  })
                  break
                case FULFILLED : 
                  promise2 = new myPromise ((resolve,reject)=>{
                    setTimeout(()=>{
                      try {
                        thenValue = resloveFun(this.fulfilledValue)
                        delFn(promise2,thenValue,resolve,reject)
                      } catch (error) {
                        reject(error)
                      }
                    },0)
                  })
                  break
                case REJECTED : 
                  promise2 = new myPromise ((resolve,reject)=>{
                    setTimeout(()=>{
                      try {
                        thenValue = rejectFun(this.rejectedValue)
                        delFn(promise2,thenValue,resolve,reject)
                      } catch (error) {
                        reject(error)
                      }
                    },0)
                  })
                  break
              }
              return promise2
            }
            catch(reject){
              return this.then(null,reject)
            }
            finally(cb){
              return this.then((val)=>{
                myPromise.reslove(cb()).then(()=>{
                  return val
                })
              },(err)=>{
                myPromise.reslove(cb()).then(()=>{
                  throw err
                })
              })
            } 
            static reslove (pro) {
              let promise
              promise = new myPromise((reslove, reject)=>{
                delFn(promise, pro, reslove, reject)
              })
              return promise
            }
            static all(proArr){
              let allPro = null
              let arr = []
              allPro = new myPromise((reslove,reject)=>{
                for(let i=0;i<proArr.length;i++){
                  myPromise.reslove(proArr[i]).then((data)=>{
                    arr[i] = proArr[i].fulfilledValue
                    if(arr.length === proArr.length){
                      reslove(arr)
                    }
                  },(err)=>{
                     reject(err)
                  })
                }
              })
              return allPro
            }
            static reject(value) {
                let promise;
                promise = new myPromise((resolve, reject)=>{
                    reject(value)
                })
                return promise
            }
            static race(arr) {
                return new myPromise((resolve, reject)=>{
                    arr.forEach(item => {
                        item.then((data)=>{
                            resolve(data)
                        },function(err){
                            reject(err)
                        })
                    });
                })
            }
          }
          win.myPromise = myPromise
        })(window)

参考链接

promise A+ 规范

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值