自定义Promise

自定义Promise

  • Promise现有的一些API
    1. Promise.prototype.then
    2. Promise.prototype.catch
    3. Promise.prototype.finally
    4. Promise.all
    5. Promise.race
    6. Promise.any
    7. Promise.allSettled
    8. Promise.resolve
    9. Promise.reject
  • 自定义Promise前所要了解下面几个问题
    1. promise的状态如何改变的:
      • promise中通过resolve()修改状态为fulfilled
      • rejecte()函数改变promise的状态为rejected
      • 也可以通过抛出异常让promise的实例变为rejected
    2. 同一个promise实例对象,使用多个then方法,如何执行:这里会有一个回调函数的数组,同一实例的多个then方法在正常情况下都会执行一遍
    3. then里面的回调和promise中的改变状态谁先谁后:这个取决于改变状态的操作是同步还是异步,如果是同步的话那就先改状态回调
    4. promise.then返回的也是一个promise对象,那么这个返回的promise对象的状态由谁决定,分为三种情况:根据then的回调函数返回的结果是否是promise以及then的执行是否出现异常
      (1) 如果执行抛出异常,return得到的promise就是失败的,reason就是error
      (2) 如果回调函数返回非promise,return的promise就会成功,value就是返回值
      (3) 如果回调函数返回的是promisereturnpromise就是根据这个返回的promise的结果
    5. promise如何串连多个then操作:then操作返回一个新的promise就可以实现多个then操作
    6. 异常传递(连续多个then后的catch操作,怎么获取到异常的)
    7. 中断promise(连续多个then时,如何在其中一个then的回调中中断后面的操作):返回一个状态为pending的新的promise

定义Promise的结构

(function (window){
	function Promise(excutor){
		
	}
	 /* 
        Promise原型对象的then方法
    */
	Promise.prototype.then = function(){
	}
	/* 
        Promise原型对象的catch方法
        指定失败的回调函数
        返回一个新的promise对象
    */
	Promise.prototype.cathc= function(){
	}
	/* 
        函数对象的all方法
        返回一个新的promise,只有当当前的promises都成功时才成功,否则失败
    */
	Promise.all= function(){
	}
	/* 
        函数对象的race方法
        返回一个新的promise,只要有一个promise成功就返回
    */
	Promise.race= function(){
	}
	/* 
        函数对象的resolve方法
        返回一个指定结果的成功的promise
    */
	Promise.resolve= function(){
	}
	/* 
        函数对象的reject方法
        返回一个指定结果的失败的promise
    */
	Promise.reject= function(){
	}
	window.Promise = Promise
})(window)

Promise执行器函数

  • 上面我们的Promise的结构定义好之后,我们开始进行下一步操作,就是我们在new Promise之后的执行器函数的初始化
    const p = new Promise(function(resolve,reject){
    	
    })
    // 下面这个方法就是执行器函数,它接收两个函数作为参数,这两个函数分别是修改状态为resolved的resolve以及修改状态为rejected的reject函数
    function(resolve,reject){
    	
    }
    
  • 通过上面解析,下面我们需要定义我们的执行器函数,且执行。这里需要主要的是我们执行器函数执行的时候可能回出现异常,当出现异常时我们需要改变promise状态为rejected,这里使用异常捕获处理
  • 既然有状态的话,那么我们就要定义三个常量进行状态的判断
  • 然后我们需要保存当前promise状态还有存储promise结果数据的属性以及回调函数数组(因为多个then的话,需要都执行)
(function (window){
	// excutor执行器函数
	const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'
	function Promise(excutor){
		const that = this
        that.status = PENDING // 给promise对象指定status属性,初始化为pending
        that.data = undefined // 给promise对象指定一个用于存储结果数据的属性
        that.callbacks = [] // 存储回调函数的数组,每个元素的结构是{onResolved({},onRejected(){}}
		function resolve() {
		}
		function reject() {
		}
		// 先捕获异常(因为在执行器执行过程中,如果出现异常就要,改变promise状态为rejected)
		try {
            excutor(resolve, reject)
        } catch (error) {
            reject(error)
        }
	}
	 /* 
        Promise原型对象的then方法
    */
	Promise.prototype.then = function(){
	}
	/* 
        Promise原型对象的catch方法
        指定失败的回调函数
        返回一个新的promise对象
    */
	Promise.prototype.cathc= function(){
	}
	/* 
        函数对象的all方法
        返回一个新的promise,只有当当前的promises都成功时才成功,否则失败
    */
	Promise.all= function(){
	}
	/* 
        函数对象的race方法
        返回一个新的promise,只要有一个promise成功就返回
    */
	Promise.race= function(){
	}
	/* 
        函数对象的resolve方法
        返回一个指定结果的成功的promise
    */
	Promise.resolve= function(){
	}
	/* 
        函数对象的reject方法
        返回一个指定结果的失败的promise
    */
	Promise.reject= function(){
	}
	window.Promise = Promise
})(window)

resolve函数以及reject函数的实现

  • 这两个函数的作用就是修改promise状态以及执行回调(这里为什么执行回调,因为如果修改状态的操作是异步的话,那么此时then后的回调函数已经搜集到了此时改变了状态之后应该立即执行回调)
  • 下面代码中的callbacks就是我们在then中搜集到的回调函数,每个元素的结构是{onResolved({},onRejected(){}}
function resolve(value) {
    // 先判断状态,如果不是pending就直接结束
    if (that.status !== PENDING) {
        return
    }
    // 修改状态
    that.status = RESOLVED
    // 保存数据
    that.data = value
    // 如果有待执行的callbacks函数,将立即异步执行回调
    if (that.callbacks.length > 0) {
        // 放到任务队列中去,当然这个只是模拟,真实情况下,不是通过定时器处理异步的
        setTimeout(() => {
            that.callbacks.forEach(callbacksObj => {
                callbacksObj.onResolved(value)
            });
        }, 0);
    }
}
function reject(reason) {
    // 先判断状态,如果不是pending就直接结束
    if (that.status !== PENDING) {
        return
    }
    // 修改状态
    that.status = REJECTED
    // 保存数据
    that.data = reason
    // 如果有待执行的callbacks函数,将立即异步执行回调
    if (that.callbacks.length > 0) {
        // 放到任务队列中去,当然这个只是模拟
        setTimeout(() => {
            that.callbacks.forEach(callbacksObj => {
                callbacksObj.onRejected(reason)
            });
        }, 0);
    }
}

then函数的实现

  • then函数的主要作用有下面
    • then函数可能回存在没有失败或者成功的回调函数,我们应该给默认值。这一步为了异常的传递
    • 判断promise的状态,如果是pending状态就搜集callbacks
    • 如果此时状态已经改变那就执行then参数中的回调
    • 返回一个新的promise
    Promise.prototype.then = function (onResolved, onRejected) {
        const that = this
        // 指定默认的失败的回调(如果没有指定onRejected回调的话,实现异常的传递)
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
        // 向后传递成功的value
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        // 返回一个新的promise对象
        return new Promise((resolve, reject) => {
            // 调用指定函数回调,根据执行的结果改变return出来的promise的状态
            function handle(callback) {
                /* 
                    1. 如果执行抛出异常,return的promise就会失败,reason就是error
                    2. 如果回调函数返回非promise,return的promise就会成功,value就是返回值
                    3. 如果回调函数返回的是promise,return的promise就是根据这个返回的promise的结果
                */
                try {
                    const result = callback(that.data)
                    if (result instanceof Promise) {
                        //3情况
                        // result.then(
                        //     value => resolve(value),
                        //     reason=> reject(reason)
                        // )
                        result.then(resolve, reason)
                    } else {
                        // 2情况
                        resolve(result)
                    }
                } catch (error) {
                    // 1情况
                    reject(error)
                }
            }
            if (that.status === PENDING) {
                // 如果当前状态还是pending时,把回调先保存起来,然后等状态改变时再执行
                that.callbacks.push({
                    onResolved(value) {
                        handle(onResolved)
                    },
                    onRejected(reason) {
                        handle(onRejected)
                    }
                })
            } else if (that.status === RESOLVED) {
                // 如果当前是resolved状态,异步执行onResolved,并改变return出来的promise的状态
                setTimeout(() => {
                    handle(onResolved)
                }, 0);
            } else {
                // 如果当前是rejected状态,异步执行onRejected,并改变return出来的promise的状态
                setTimeout(() => {
                    handle(onRejected)
                }, 0);
            }
        })
    }

catch的实现

  • catch就是then(undefined,onRejected)
    Promise.prototype.catch = function (onRejected) {
        return this.then(undefined, onRejected)
    }

resolve

    Promise.resolve = function (value) {
        // 返回一个成功/失败的promise
        return new Promise((resolve, reject) => {
            if(value instanceof Promise) { // 使用value的结果作为new promise的结果
                value.then(resolve,reject)
            } else {
                resolve(value)
            }
        })
    }

reject

  Promise.reject = function (reason) {
        return new Promise((resolve, reject) => {
            reject(reason)
        })
    }

race

    Promise.race = function (promises) {
        // 用来保存
        return new Promise((resolve,reject)=>{
            promises.forEach((p,index) => {
                Promise.resolve(p).then(
                    value => {
                        resolve(value)
                    },
                    reason => {
                        reject(reason)
                    }
                )
            });
        })
    }

all

Promise.all = function (promises) {
        // 用来保存
        const values = new Array(promises.length)
        let resolveCount = 0
        return new Promise((resolve,reject)=>{
            promises.forEach((p,index) => {
                Promise.resolve(p).then(
                    value => {
                        resolveCount++
                        values[index] = value
                        if(resolveCount == promises.length){
                            resolve(values)
                        }
                    },
                    reason => {
                        reject(reason)
                    }
                )
            });
        })
    }

总体代码如下

(function (window) {
    // 状态常量
    const PENDING = 'pending'
    const RESOLVED = 'resolved'
    const REJECTED = 'rejected'

    function Promise(excutor) {
        const that = this
        that.status = PENDING
        that.data = undefined
        that.callbacks = [] // 每个元素的类型如下:{onResolved:xxx,onRejected:xxxx}
        // 下面两个方法的作用就是改变状态,执行回调
        function resolve(value) {
            if(that.status !== PENDING){
                return
            }
            that.status = RESOLVED
            that.data = value
            if(that.callbacks.length>0){
                that.callbacks.forEach(callbackObj => {
                    // 这个回调模拟了一些异步任务,不过正常Promise不是通过setTimeout宏任务执行的
                    setTimeout(() => {
                        callbackObj.onResolved(value)   
                    },0);
                });
            }
        }
        
        function reject(reason) {
            if(that.status !== PENDING){
                return
            }
            that.status = REJECTED
            that.data = reason
            if(that.callbacks.length>0){
                that.callbacks.forEach(callbackObj => {
                    // 这个回调模拟了一些异步任务,不过正常Promise不是通过setTimeout宏任务执行的
                    setTimeout(() => {
                        callbackObj.onRejected(reason)   
                    },0);
                });
            }
        }
        try {
            excutor(resolve,reject)
        } catch (error) {
            reject(error)
        }
        
    }
    Promise.prototype.then = function (onResolved,onRejected) {
        const that = this
        //  then方法的作用就是收集回调(onResolved,onRejected)
        //  在then方法中需要对onResolved,onRejected给默认值(就是没有指定onResolved,onRejected回调的时候)
        // 指定默认的失败的回调(如果没有指定onRejected回调的话,实现异常的传递)
        onRejected = typeof onRejected === 'function' ? onRejected : reason => { throw reason }
        // 向后传递成功的value
        onResolved = typeof onResolved === 'function' ? onResolved : value => value
        //  返回一个promise对象,而这个promise的结果就是onResolved,onRejected的执行结果
        return new Promise((resolve,reject) => {
            if(that.status === PENDING){ 
                // 当前状态为pending时,收集回调到callbacks数组中
                that.callbacks.push({
                    onResolved () {
                        // onResolved(that.data)
                        try {
                            const result = onResolved(that.data)
                            if (result instanceof Promise) {
                                result.then(resolve, reason)
                            } else {
                                // 2情况
                                resolve(result)
                            }
                        } catch (error) {
                            // 1情况
                            reject(error)
                        }
                    },
                    onRejected () {
                        try {
                            const result = onRejected(that.data)
                            if (result instanceof Promise) {
                                result.then(resolve, reason)
                            } else {
                                // 2情况
                                resolve(result)
                            }
                        } catch (error) {
                            // 1情况
                            reject(error)
                        }
                    }
                })
            } else if(that.status === RESOLVED){
                // 此时状态已经改变,这时需要立即执行回调
                setTimeout(() => {
                    // 根据onResolved(that.data)返回的结果,给return 新的promise的设置状态
                    // onResolved(that.data)如果异常的话 return的promise的状态为rejected
                    // onResolved(that.data)返回的如果不是一个promise的话, return的promise的状态为resolved value就是onResolved(that.data)返回值
                    // onResolved(that.data)返回的如果是一个promise的话, return的promise的状态就是onResolved(that.data)返回的状态
                    try {
                        const result = onResolved(that.data)
                        if(result instanceof Promise){
                            result.then(
                                value => resolve(value),
                                reason => reject(reason)
                            )
                        } else {
                            resolve(result)
                        }
                    } catch (error) {
                        reject(error)
                    }
                });
            } else {
                setTimeout(() => {
                    try {
                        const result = onRejected(that.data)
                        if(result instanceof Promise){
                            result.then(
                                value => resolve(value),
                                reason => reject(reason)
                            )
                        } else {
                            resolve(result)
                        }
                    } catch (error) {
                        reject(error)
                    }
                });
            }
        })
    }

    Promise.prototype.catch = function (onRejected) {
        // Promise.prototype.then(undefined,onRejected)
        return this.then(undefined, onRejected)
    }

    Promise.resolve = function (value) {
        return new Promise((resolve,reject)=>{
            // 返回promise的时候需要注意value是不是 promise对象,如果是的话,那返回的promise的状态就是由value的状态决定
            if(value instanceof Promise){
                value.then(resolve,reject)
            } else {
                resolve(value)
            }
        })
    }

    Promise.reject = function (reason) {
        // Promise.reject不会处理像上面resolve函数那样处理传进来的是promise对象的问题
        return new Promise((resolve,reject)=>{
            reject(reason)
        })
    }

    Promise.all = function (promises) {
        let count = 0;
        let values = new Array(promises.length)
        return new Promise((resolve,reject)=>{
            promises.forEach((p,index) => {
                Promise.resolve(p).then(
                    value => {
                        count++
                        values[index] = value
                        // 这个地方等所有的then执行完再改变状态
                        if(count  == promises.length){
                            resolve(values)
                        }
                    },
                    reason => reject(reason)
                )
            });
         })
    }

    Promise.race = function (promises) {
        return new Promise((resolve,reject)=>{
           promises.forEach(p => {
               Promise.resolve(p).then(
                   value => resolve(value),
                   reason => reject(reason)
               )
           });
        })
    }
    window.Promise = Promise
})(window)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值