js之从Promise的基本使用模拟Promise源码

分析Promise的基本使用

  1. Promise就是一个类
class MyPromise {}
  1. 执行这个类的时候,需要传递一个执行器(回调函数),执行器会立即执行
class MyPromise{
    constructor(executor){ 
        executor()    
    }
}
  1. 执行器有两个参数,resolve和reject 为两个函数
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    resolve = () =>{

    }
    reject = () =>{

    }
}
  1. Promise有三种状态(status)分别为: 成功(fulfilled) 失败(rejected) 等待(pending)。
const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    resolve = () =>{
    }
    reject = () =>{
    }
}

5.resolve :把Promise 状态改为 fulfilled ;reject把Promise 状态改为rejected

const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    resolve = () =>{
        this.status = FULFILLED
    }
    reject = () =>{
        this.status = REJECTED
    }
}
  1. 一旦状态确定就不可更改 比如 pending --> fulfilled ;pending --> rejected
const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    resolve = () =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
    }
    reject = () =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
    }
}
  1. resolve 参数为成功后的数据;reject 参数为失败之后的原因
const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    data = undefined
    reason = undefined
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
    }
}
  1. then 方法被定义在原型对象中,then方法内部做的事情就是判断状态,如果成功,调用成功的回调,参数为成功的数据,如果失败,调用失败的回调,参数为失败的原因
const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    data = undefined
    reason = undefined
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
    }
    then(successCallback,failCallback){
        if(this.status === FULFILLED){
            successCallback(this.data)
        } else if (this.status === REJECTED){
            failCallback(this.reason)
        }
    }
}

8.执行器中有异步操作时,then不会立即得到成功还是失败的状态,因此需要把成功后的回调和失败后的回调存储起来,等待异步操作完成后再执行对应的回调

const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    data = undefined
    reason = undefined
    successCallback = undefined
    failCallback = undefined
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
        this.successCallback && this.successCallback(this.data)
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
        this.failCallback && this.failCallback(this.reason)
    }
    then(successCallback,failCallback){
        if(this.status === FULFILLED){
            successCallback(this.data)
        } else if (this.status === REJECTED){
            failCallback(this.reason)
        } else {
            this.successCallback = successCallback
            this.failCallback = failCallback
        }
    }
}

9.同一个Promise对象,多次调用then方法时,异步情况需要添加多个回调函数依次执行,做以下修改
修改成功回调和失败回调的数据类型为数组
then方法中Promise为等待的状态时,push成功回调和失败回调到数组
异步操作完成后,按顺序执行成功或失败的回调函数

const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    data = undefined
    reason = undefined
    successCallback = []
    failCallback = []
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
        //this.successCallback && this.successCallback(this.data)
        while(this.successCallback.length) this.successCallback.shift()(this.data)
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
        //this.failCallback && this.failCallback(this.reason)
        while(this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback,failCallback){
        if(this.status === FULFILLED){
            successCallback(this.data)
        } else if (this.status === REJECTED){
            failCallback(this.reason)
        } else {
            this.successCallback.push(successCallback)
            this.failCallback.push(failCallback)
        }
    }
}

10.实现then方法的链式调用,做以下修改
then方法每次要返回一个新的Promise对象
处理then方法的返回值(非Promise类型)到新的Promise对象执行器的reslove方法中,以实现链式调用时返回值的传递

const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    data = undefined
    reason = undefined
    successCallback = []
    failCallback = []
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
        //this.successCallback && this.successCallback(this.data)
        while(this.successCallback.length) this.successCallback.shift()(this.data)
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
        //this.failCallback && this.failCallback(this.reason)
        while(this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback,failCallback){
        return new MyPromise((resolve,reject) => {
            if(this.status === FULFILLED){
               let returnValue = successCallback(this.data)
               resolve(returnValue)
            } else if (this.status === REJECTED){
                failCallback(this.reason)
            } else {
                this.successCallback.push(successCallback)
                this.failCallback.push(failCallback)
            } 
        })
    }
}

10.1 当then 方法成功的回调函数中,返回的是一个Promise对象时,做以下修改
判断returnValue的类型
如果是Promise创建的实例,则需要把成功还是失败的回调传递到新的Promise对象中以实现链式调用
如果是非Promise创建的实例,则需要把返回值(returnValue)传递到reslove中

const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    data = undefined
    reason = undefined
    successCallback = []
    failCallback = []
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
        //this.successCallback && this.successCallback(this.data)
        while(this.successCallback.length) this.successCallback.shift()(this.data)
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
        //this.failCallback && this.failCallback(this.reason)
        while(this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback,failCallback){
        return new MyPromise((resolve,reject) => {
            if(this.status === FULFILLED){
               let returnValue = successCallback(this.data)
               if(returnValue instanceof MyPromise){
                returnValue.then(resolve,reject)
               } else {
                resolve(returnValue)
               }
            } else if (this.status === REJECTED){
                failCallback(this.reason)
            } else {
                this.successCallback.push(successCallback)
                this.failCallback.push(failCallback)
            } 
        })
    }
}

11.异常处理,当then方法的成功回调函数中,返回then方法返回的Promise对象时,也就是自己调用自己的情况,系统中的Promise对象会抛出TypeError的异常。对我们的MyPromise做以下修改以捕获类似异常
在then方法中做判断,返回新的Promise对象与成功回调返回的值(returnValue)相等的时候,调用新的Promise的rejece方法并传入类型异常
把判断的代码做成异步代码,不然无法拿到新的Promise对象 (setTimeout 0)
添加新方法 resolvePromise 用来判断then方法成功回调的返回值

const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        executor(this.resolve,this.reject)
    }
    status = PENDING
    data = undefined
    reason = undefined
    successCallback = []
    failCallback = []
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
        //this.successCallback && this.successCallback(this.data)
        while(this.successCallback.length) this.successCallback.shift()(this.data)
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
        //this.failCallback && this.failCallback(this.reason)
        while(this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback,failCallback){
        let newMyPromise = new MyPromise((resolve,reject) => {
            if(this.status === FULFILLED){
               setTimeout(() => {
                let returnValue = successCallback(this.data)
                resolvePromise(newMyPromise,returnValue,resolve,reject)
               }, 0);
            } else if (this.status === REJECTED){
                failCallback(this.reason)
            } else {
                this.successCallback.push(successCallback)
                this.failCallback.push(failCallback)
            } 
        })
        return newMyPromise
    }
}
function resolvePromise (newMyPromise,returnValue,resolve,reject){
    if(newMyPromise  === returnValue){
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }else{
        if(returnValue instanceof MyPromise){
            returnValue.then(resolve,reject)
        } else {
            resolve(returnValue)
        }
    }
}

12 捕获及处理执行器和then方法的成功回调函数的异常以及then方法中失败和等待时链式调用的实现
给执行器和then方法的回调函数加上异常处理
把then方法失败和等待状态的链式调用实现成之前成功状态的代码

const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        try{
            executor(this.resolve,this.reject)
        }catch(error){
            this.reject(error)
        }
    }
    status = PENDING
    data = undefined
    reason = undefined
    successCallback = []
    failCallback = []
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
        while(this.successCallback.length) this.successCallback.shift()()
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
        while(this.failCallback.length) this.failCallback.shift()()
    }
    then(successCallback,failCallback){
        let newMyPromise = new MyPromise((resolve,reject) => {
            if(this.status === FULFILLED){
               setTimeout(() => {
                try{
                    let returnValue = successCallback(this.data)
                    resolvePromise(newMyPromise,returnValue,resolve,reject)
                }catch(error){
                    reject(error)
                }
               }, 0);
            } else if (this.status === REJECTED){
                setTimeout(() => {
                    try{
                        let returnValue = failCallback(this.reason)
                        resolvePromise(newMyPromise,returnValue,resolve,reject)
                    }catch(error){
                        reject(error)
                    }
                   }, 0);
            } else {
                this.successCallback.push(()=>{
                    setTimeout(() => {
                        try{
                            let returnValue = successCallback(this.data)
                            resolvePromise(newMyPromise,returnValue,resolve,reject)
                        }catch(error){
                            reject(error)
                        }
                       }, 0);
                })
                this.failCallback.push(() =>{
                    setTimeout(() => {
                        try{
                            let returnValue = failCallback(this.reason)
                            resolvePromise(newMyPromise,returnValue,resolve,reject)
                        }catch(error){
                            reject(error)
                        }
                       }, 0);
                })
            } 
        })
        return newMyPromise
    }
}
function resolvePromise (newMyPromise,returnValue,resolve,reject){
    if(newMyPromise  === returnValue){
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }else{
        if(returnValue instanceof MyPromise){
            returnValue.then(resolve,reject)
        } else {
            resolve(returnValue)
        }
    }
}

13.将then 方法的参数变成可选参数,也就是说 当then方法链式调用的时候 先不传参数 后面的then再穿参数,也可以调用then的回调函数
做法就是判断then的参数如果为空,补上成功或失败的回调函数

const PENDING = 'pending' 
const FULFILLED = 'fulfilled' 
const REJECTED = 'rejected' 
class MyPromise{
    constructor(executor){
        try{
            executor(this.resolve,this.reject)
        }catch(error){
            this.reject(error)
        }
    }
    status = PENDING
    data = undefined
    reason = undefined
    successCallback = []
    failCallback = []
    resolve = data =>{
        if(this.status !== PENDING) return
        this.status = FULFILLED
        this.data = data
        while(this.successCallback.length) this.successCallback.shift()()
    }
    reject = reason =>{
        if(this.status !== PENDING) return
        this.status = REJECTED
        this. reason = reason
        while(this.failCallback.length) this.failCallback.shift()()
    }
    then(successCallback,failCallback){
        let newMyPromise = new MyPromise((resolve,reject) => {
            if(this.status === FULFILLED){
               setTimeout(() => {
                try{
                    if(!successCallback) successCallback = value  => value
                    let returnValue = successCallback(this.data)
                    resolvePromise(newMyPromise,returnValue,resolve,reject)
                }catch(error){
                    reject(error)
                }
               }, 0);
            } else if (this.status === REJECTED){
                setTimeout(() => {
                    try{
                        if(!failCallback) failCallback = reason => { throw reason }
                        let returnValue = failCallback(this.reason)
                        resolvePromise(newMyPromise,returnValue,resolve,reject)
                    }catch(error){
                        reject(error)
                    }
                   }, 0);
            } else {
                this.successCallback.push(()=>{
                    setTimeout(() => {
                        try{
                            if(!successCallback) successCallback = value  => value
                            let returnValue = successCallback(this.data)
                            resolvePromise(newMyPromise,returnValue,resolve,reject)
                        }catch(error){
                            reject(error)
                        }
                       }, 0);
                })
                this.failCallback.push(() =>{
                    setTimeout(() => {
                        try{
                            if(!failCallback) failCallback = reason => { throw reason }
                            let returnValue = failCallback(this.reason)
                            resolvePromise(newMyPromise,returnValue,resolve,reject)
                        }catch(error){
                            reject(error)
                        }
                       }, 0);
                })
            } 
        })
        return newMyPromise
    }
}
function resolvePromise (newMyPromise,returnValue,resolve,reject){
    if(newMyPromise  === returnValue){
        reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }else{
        if(returnValue instanceof MyPromise){
            returnValue.then(resolve,reject)
        } else {
            resolve(returnValue)
        }
    }
}

14.Promise.all 方法的实现

    static all (array){
        let result = []
        return new MyPromise(async (resolve,reject) =>{
            for(let item of array){
                if(item instanceof MyPromise){
                    try{
                        result.push(await item)
                    }catch(error){
                        reject(error)
                    }
                }else{
                    result.push(item)
                }
            }
            resolve(result)
        })
    }

上面是直接拍扁异步操作或者等待异步操作完成以后,再去resolve,两个方式都可以实现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++){
                if(array[i] instanceof MyPromise){
                    array[i].then(value => addData(i,value), error => reject(error))
                }else{
                    addData(i,array[i])
                }
            } 
        })
    }

15.Promise.resolve方法的实现

    static resolve(value){
        if(value instanceof MyPromise){
            return value
        }else{
            return new MyPromise(resolve =>resolve(value))
        }
    }

16.finally 方法的实现

    finally(Callback){
        return this.then(value =>{
            return MyPromise.resolve(Callback()).then(() => value) 
        },error =>{
            return MyPromise.resolve(Callback()).then(() => { throw error }) 
        })
    }

17.catch 方法的实现

    catch(failCallback){
        return this.then(undefined,failCallback)
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值