手动实现promise源码

Posted 全力以赴

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手动实现promise源码相关的知识,希望对你有一定的参考价值。

promise是异步解决方案,解决回调地狱问题。promise从语法上来说是一个构造函数。从功能来说封装异步操作,并且可以获取其操作结果。

1.基本用法

    const p =new Promise((resolve,reject)=>{
        setTimeout(()=>{
            //异步操作
            resolve(value)
        },100)

    })

构造函数Promise的参数为一个执行器函数,执行器函数的参数为resolve与reject分别代表:第一个回调函数是Promise对象的状态变为resolved时调用,第二个回调函数是Promise对象的状态变为rejected时调用
2.Promise构造函数的实现

Promise对象内部含有三种状态,初始值pending 已成功 resolved 已失败 rejected
内部的状态在执行过程中,状态只能改变一次并且不可逆。 

初始化 初始时候将status的状态为pending callbacks用来保存成功的与失败的回调函数

        self.status =PENDING
        self.data =undefined
        self.callbacks =[] //每个元素结构 {onResolved(){}  onRejected(){}  }
    function Promise(excutor){
        const self =this
        self.status =PENDING
        self.data =undefined
        self.callbacks =[] //每个元素结构 {onResolved(){}  onRejected(){}  }
        function resolve(value){
            // resolve函数的作用将promise状态变为resolved
            if(self.status!==PENDING){
                //如果不是pending状态直接返回
                return
            }
            self.status =RESOLVED
            self.data = value
            if(self.callbacks.length>0){
               setTimeout(() => {
                    self.callbacks.forEach(callbacksObj => {
                        callbacksObj.onResolved(value)
                        
                    });  
                },0);
    
            }
        }
        function reject(reason){
            if(self.status!==PENDING){
                return
            }
            self.status =REJECTED
            self.data = reason
            if(self.callbacks.length>0){
               setTimeout(() => {
                   //遍历回调队列
                    self.callbacks.forEach(callbacksObj => {
                        callbacksObj.onRejected(reason)
                        
                    });  
                });
    
            }

        }
       //立即同步执行ex
       try{
        excutor(resolve,reject)

       }catch(err){
           reject(err)
       }       
    }

3.promise实例的then方法

then方法的第一个参数是resolved状态的回调函数,第二个参数是rejected状态的回调函数,它们都是可选的。并且返回也是一个Promise对象有三种情况
  • 如果回调函数返回是promise return的promise的结果就是这个promise的结果
  • 如果回调函数返回不是promise return的promise就会成功 value就是返回值
  • 如果抛出异常 return的promise就会失败 resaon就是error
    Promise.prototype.then=function(onResolved,onRejected){
        const self =this
        onResolved = typeof onResolved === \'function\' ? onResolved :value =>value
        onRejected = typeof onRejected === \'function\' ? onRejected :reason =>{throw reason}
        //返回一个新的promise 对象 
        return new Promise((resolve,reject)=>{
        //调用指定的回调函数处理、根据执行结果 改变return的promise状态
        function handle(callback){
            try{
                const result =callback(self.data)
                if(result instanceof Promise){
                    //如果回调函数返回是promise return的promise的结果就是这个promise的结果
                    result.then(value =>{
                         resolve(value)

                    },reason =>{
                         reject(reason)

                    })
                    // result.then(resolve,reject)

                }else{
                    //如果回调函数返回不是promise return的promise就会成功 value就是返回值
                    resolve(result)
                }
            }catch(error){
             //如果抛出异常 return的promise就会失败 resaon就是error
                reject(error)

            } 
        }
            if(self.status === PENDING){
                self.callbacks.push({
                    onResolved(){
                        handle(onResolved)
                    },
                    onRejected(){
                        handle(onRejected) 
                    }
                })
    
            }else if(self.status === RESOLVED){
                setTimeout(()=>{
                    handle(onResolved)
                })
    
            }else{
                setTimeout(()=>{
                    handle(onRejected)
                })
            }
        })
         
    }

4.Promise对象的catch方法

作用来捕获发生错误的回调方法
    Promise.prototype.catch=function(onRejected){
        return this.then(undefined,onRejected)  
    }

5 Promise的resolve方法

作用是将对象变为Promise对象。如果resolve方法参数是非Promise对象直接将value传递下去,如果是Promise对象value的结果将作为Promise的结果
    Promise.resolve = function(value){
        return new Promise((resolve,reject)=>{
            //value是promise
            if(value instanceof Promise){
                //使用value的结果作为promise的结果
                value.then(resolve,reject)
            }else{
                  //value不是promise
                  resolve(value)
            }
        })
    }

6.Promise的reject方法

作用返回一个rejected的Promise对象
    Promise.reject = function(reason){
        return new Promise((resolve,reject)=>{
            reject(reason)
        })
    }

7.Promise的all方法

  作用:执行多个Promise 并返回新的Promise实例
  all方法接收一个数组参数:
  • 如果Promise对象全部成功,将返回一个数组保存每个成功的Promise的返回值。
  • 如果有一个Promise对象失败 新的Promise将变为失败 返回值为执行失败的Promise的返回值
    Promise.all = function(promises){
        //用来保存所有成功value的数组
        const values =new Array(promises.length)
        //用来保存成功promise的数量
        let count = 0 
        return new Promise((resolve,reject)=>{
            //获取每个promise的结果
            promises.forEach((p,index)=>{
                Promise.resolve(p).then(value=>{
                    count++
                    values[index] = value //保存成功的值
                    //如果全部成功了,将return的promise变为成功

                    if(count === promises.length){
                        resolve(values)
                    }
                },reason =>{
                    reject(reason)
                })

            })
        })

    }

8.Promise的race方法

 作用:返回一个新的Promise对象,最先执行完成Promise的返回值作为新的Promise对象的结果
    Promise.race = function(promises){
        return new Promise((resolve,reject)=>{
            //获取每个promise的结果
            promises.forEach((p)=>{
                Promise.resolve(p).then(value=>{
                    resolve(value)
                },reason =>{
                    reject(reason)
                })
            })
        })
    }

以上是关于手动实现promise源码的主要内容,如果未能解决你的问题,请参考以下文章

VSCode自定义代码片段12——JavaScript的Promise对象

从源码看 Promise 概念与实现

JS-JS模拟实现Promise-源码解析

手动实现Promise.all()

手动实现 Promise

手动实现最简版promise