最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • Promise规范解读及简易实现

    正文概述 掘金(volibear)   2021-01-31   450

    Promise详解

    为什么需要Promise

    JavaScript是一门单线程语言,所以早期我们解决异步的场景时,大部分情况都是通过回调函数来处理。 例如,在浏览器中发送ajax请求,就是常见的一个异步场景,发送请求后,一段时间服务端响应之后我们才能拿到结果。如果我们希望在异步结束之后执行某个操作,就只能通过回调函数这样的方式进行操作。

    const dynamicFunc = function (cb) {
        setTimeout(() => {
            cb()
        }, 1000)
    }
    dynamicFunc(function () {
        console.log(123)
    })
    

    上面这个例子中dynamicFunc就是一个异步函数,里面执行的setTimeout会在1s之后将cb函数放入事件队列,待主线程代码执行完后调用cb函数。按照上面的调用方式,最终延迟1s后会打印123这个结果。 同样的,如果后续还有内容需要在异步函数结束时输出的话,就需要多个异步函数进行嵌套,非常不利于后续的维护。

    Promise是如何使用的

    在支持ES6的高级浏览器环境中,我们通过new Promise()即可创建一个promise实例。 这个构造函数接收一个函数,分别接收两个参数:resolve和reject,代表着改变当前实例的状态为已完成或者已拒绝

    function promise1() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('1s后输出')
                resolve();
            }, 1000)
        })
    }
    
    function promise2() {
        return new Promise((resolve, reject) => {
            setTimeout(() => {
                console.log('2s后输出')
                resolve();
            }, 2000)
        })
    }
    

    上面两个promise实例,串联起来即可写为: promise1().then(() => promise2()) 也可以简写为: promise1().then(promise2)

    浏览器中执行之后,即可看到,1s之后出现1s后输出字样,在经过2s出现2s后输出字样。在这个例子中我们能看到:当前promise如果状态变为已完成(执行了resolve方法),那么就会去执行then方法中的下一个promise函数。

    同样的,如果promise变为已拒绝状态(执行了reject方法),那么就会进入后续的异常处理函数中。

    function promise3() {
        return new Promise(function (resolve, reject) {
            var random = Math.random() * 10;
            setTimeout(function () {
                if (random >= 5) {
                    resolve(random);
                } else {
                    reject(random);
                }
            }, 1000);
        });
    }
    
    var onResolve = function (val) {
        console.log('已完成:输出的数字是:', val);
    };
    var onReject = function (val) {
        console.log('已拒绝:输出的数字是:', val);
    }
    
    promise3().then(onResolve, onReject);
    
    // 可以通过catch方法拦截状态变为已拒绝的promise
    promise3().catch(onReject).then(onResolve);
    
    // 也可以通过try catch 拦截状态变为已拒绝的promise
    try {
        promise3().then(onResolve);
    } catch (e) {
        onReject(e);
    }
    

    这个例子使用了三种方式拦截最终变为已拒绝状态的promise,分别使用then的第二个参数,使用.catch方法捕获前方promise抛出的异常,使用try catch拦截代码块中promise抛出的异常

    同时,我们还发现,在改变promise状态时调用resolve和reject函数的时候,也可以给下一步then中执行的函数传递参数。这个例子中把随机生成的数字传给了resolve和reject函数,我们也就能在then中执行函数的时候拿到这个值。

    总结:

    1. promise会有三种状态,进行中 已完成 已拒绝,进行中状态可以更改为已完成或已拒绝,已经更改过状态后无法继续更改(例如不能从已完成改为已拒绝)
    2. ES6中的Promise构造函数,需要传入一个函数,接收两个函数参数,执行第一个参数之后就会改变当前promise为已完成状态,执行第二个参数之后就会变为已拒绝状态
    3. 通过.then方法,即可在上一个promise变为已完成状态时继续执行下一个函数或promise。同时,通过resolve或reject时传递参数,即可给下一个函数或promise传入初始值
    4. 已拒绝的promise后续可以通过.catch方法或者.then方法的第二个参数或者try catch进行捕获

    promise规范解读

    任何符合promise规范的对象或函数都可以成为promise,promises/A+规范地址:https://promisesaplus.com/

    上面我们熟悉了整体promise的用法,知道了如何去创建一个promise,如何使用它,也熟悉了如何去改造回调函数到promise。本小节我们详细过一遍promises/A+规范,从规范层面明白Promise使用过程中的细节。

    术语

    • Promise:promise是一个拥有then方法的对象或函数,其行为符合本规范
    • 具有then方法(thenable):是一个定义了then方法的对象或函数
    • 值(value):指任何JavaScript的合法值(包括undefined,thenable和promise)
    • 异常(exception):是使用throw语句抛出的一个值
    • 原因(reason):表示一个promise的拒绝原因

    要求

    promise的状态

    一个Promise的当前状态必须为一下三种状态中的一种:等待态(Pending)、已完成(Fulfilled)、已拒绝(Rejected)

    • 处于等待态时,promise需满足一下条件:可以变为已完成已拒绝
    • 处于已完成时,promise需满足一下条件:1.不能改变为其他任何状态 2.必须拥有一个不可变的值
    • 处于已拒绝时,promise需满足以下条件:1.不能改变为其他任何状态 2.必须拥有一个不可变的原因

    必须有一个then方法

    一个promise必须提供一个then方法以访问其当前值和原因。 promise的then方法接收两个参数:promise.then(onFulfilled, onRejected)他们都是可选参数,同时他们都是函数,如果onFulfilledonRejected不是函数,则需要忽略他们。

    • 如果onFulfilled是一个函数
      • promise执行结束后其必须被调用,其第一个参数为promise的结果
      • promise执行结束前其不可被调用
      • 其调用次数不可超过一次
    • 如果onRejected是一个函数
      • promise被拒绝执行后其必须被调用,其第一个参数为promise的原因
      • promise被拒绝执行前其不可被调用
      • 其调用次数不可超过一次
    • 在执行上下文堆栈仅包含平台代码之前,不得调用onFulfilledonRejected
    • onFulfilledonRejected必须被作为普通函数调用(即非实例化调用,这样函数内部this非严格模式下指向window)
    • then方法可以被同一个promise调用多次
      • promise成功执行时,所有onFulfilled需按照其注册顺序依次回调
      • promise被拒绝执行时,所有的onRejected需按照其注册顺序依次回调
    • then方法必须返回一个promise对象promise2 = promise1.then(onFulfilled, onRejected)
      • 只要onFulfilledonRejected返回一个值x,promise2都会进入onFulfilled状态
      • 只要onFulfilledonRejected抛出一个异常e,则promise2必须拒绝执行,并返回原因e
    • 如果onFulfilled不是函数且promise1状态变为已完成,promise2必须成功执行并返回相同的值
    • 如果onRejected不是函数且promise1状态变为已拒绝,promise2必须执行拒绝回调并返回相同的原因
    var promise1 = new Promise((resolve, reject) => { reject(); });
    promise1
        .then(null, function () {
            return 123;
        })
        .then(null, null)
        .then(null, null)
        .then(
            () => {
                console.log('promise2已完成');
            },
            () => {
                console.log('promise2已拒绝');
            });
    

    promise的解决过程

    **promise解决过程是一个抽象的操作,其需输入一个promise和一个值,我们表示为[[Resolve]](promise, x)(这句话的意思就是把promise resolve,同时传入x作为值)

    promise.then(x => {
        console.log('会执行这个函数,同时传入x变量的值: ', x)
    })
    

    如果xthen方法且看上去像一个Promise,解决程序即尝试使promise接受x的状态;否则其用x的值来执行promise

    • 如果promisex指向同一个对象,以TypeError为原因拒绝执行promise
    • 如果xpromise
      • 如果x处于等待态,promise需保持为等待态直至x被执行或拒绝
      • 如果x处于执行态,用相同的值执行promise
      • 如果x处于拒绝态,用相同的原因拒绝promise
    var promise1 = function () {
        return new Promise(function (resolve) {
            setTimeout(function () {
                console.log(1);
                resolve();
            }, 1000)
        });
    }
    var promise2 = function () {
        return new Promise(function (resolve) {
            setTimeout(function () {
                console.log(2);
                resolve();
            }, 2000);
        });
    }
    promise1()
        .then(function () {
            return promise2(); // 此处返回一个promise实例
        })
        .then(function () { console.log('已完成') }, function () { console.log('已拒绝') });
    
    • 如果x为Object或function(不常见)
      • 首先尝试执行x.then
      • 如果取x.then的值时抛出错误e,则以e为原因拒绝promise
      • 如果then是函数,将x作为函数的作用域this调用。传递两个回调函数作为参数,第一个参数叫做resolvePromise,第二个叫做rejectPromise
        • 如果resolvePromise以值y为参数被调用,则运行`[[Resolve]](promise, y)
        • 如果rejectPromise以据因r为参数被调用,则以据因r拒绝promise
        • 如果resolvePromiserejectPromise均被调用,或者被同一参数调用了多次,则优先采用首次调用并忽略其他的调用
        • 如果调用then方法抛出了异常e
          • 如果resolvePromiserejectPromise已被调用,则忽略
          • 否则以e为据因拒绝promise
      • 如果then不为函数,以x为参数将promise变为已完成状态
    • 如果x不为对象或者函数,以x为参数将promise变为已完成状态**(重要且常见)**

    Promise构造函数上的静态方法

    Promise.resolve

    返回一个promise实例,并将它的状态设置为已完成,同时将它的结果作为传入promise实例的值

    var promise = Promise.resolve(123);
    promise
        .then(function (val) {
            console.log('???', val);
        });
    // 已完成 123
    

    同样的,Promise.resolve的参数也可以处理对象、函数等内容,处理方式和上面规范中介绍的相同。

    Promise.reject

    返回一个promise实例,并将它的状态设置为已拒绝,同时也将它的结果作为原因传入onRejected函数

    var promise = Promise.reject(123);
    promise
        .then(null, function (val) {
            console.log('已拒绝', val);
        });
    // 已拒绝 123
    

    Promise.all

    返回一个promise实例,接收一个数组,里面含有多个promise实例,当所有promise实例都成为已完成状态时,进入已完成状态,否则进入已拒绝状态。

    var promise1 = function () {
        return new Promise(function (resolve) {
            setTimeout(function () {
                console.log(1);
                resolve();
            }, 1000)
        });
    }
    var promise2 = function () {
        return new Promise(function (resolve) {
            setTimeout(function () {
                console.log(2);
                resolve();
            }, 2000);
        });
    }
    
    Promise.all([promise1(), promise2()])
        .then(function () {
            console.log('全部promise均已完成');
        });
    

    注意,此时多个promise是同时进行的,也就是在上面这个例子中,等待1s打印1之后,在等待1s就会打印打印2和'全部promise均已完成'。

    Promise.race

    返回一个promise实例,接收一个数组,里面含有多个promise实例,当有一个promise实例状态改变时,就进入该状态且不可改变。这里所有的promise实例为竞争关系,只选择第一个进入改变状态的promise的值。

    var promise1 = function () {
        return new Promise(function (resolve) {
            setTimeout(function () {
                console.log(1);
                resolve(1);
            }, 1000)
        });
    }
    var promise2 = function () {
        return new Promise(function (resolve) {
            setTimeout(function () {
                console.log(2);
                resolve(2);
            }, 2000);
        });
    }
    Promise.race([promise1(), promise2()])
        .then(function (val) {
            console.log('有一个promise状态已经改变:', val);
        });
    

    实现一个简易的promise

    Promise类核心逻辑实现

    1. Promise就是一个类,在对这个类进行实例化的时候要传递一个执行器函数,并且执行器立即执行
    2. Promise中对应三种状态:成功(fulfilled)失败(rejected)等待(pending)
    3. 执行resolve方法的时候状态由pending变为fulfilled,执行reject方法的时候状态由pending变为rejected,而且状态一经确定便不可再更改
    4. then方法定义在原型对象中,接收两个参数分别为成功的回调函数和失败的回调函数
    5. then方法作用为判断状态,状态成功则调用成功的回调函数(参数表示成功传递的值),状态失败则调用失败的回调函数(参数表示失败的原因)
    // 定义常量的目的:1.表示promise的不同状态 2.可以让编辑器有代码提示(哈哈)
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            executor(this.resolve, this.reject)
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
        }
        then(successCb, failCb) {
            // 判断状态
            if (this.status === FULFILLED) { // 同步调用
                successCb(this.successData) // 调用成功回调,把值返回
            } else if (this.status === REJECTED) { // 同步调用
                failCb(this.failReason) // 调用失败回调,把原因返回
            }
        }
    }
    
    const promise = new MyPromise((resolve, reject) => {
        resolve('success')
        // reject('fail')
    });
    
    promise.then(val => {
        console.log(val)
    }, reason => {
        console.log(reason)
    })
    

    Promise中加入异步逻辑

    上面代码是没有经过异步处理的,如果有异步逻辑则会出现问题

    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            executor(this.resolve, this.reject)
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = undefined // 存储成功的回调函数
        failCallback = undefined // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            this.successCallback && this.successCallback(this.successData) // 异步逻辑下调用成功的回调
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            this.failCallback && this.failCallback(this.failReason) // 异步逻辑下调用失败的回调
        }
        then(successCb, failCb) {
            // 判断状态
            if (this.status === FULFILLED) { // 同步调用
                successCb(this.successData) // 调用成功回调,把值返回
            } else if (this.status === REJECTED) { // 同步调用
                failCb(this.failReason) // 调用失败回调,把原因返回
            } else { // 异步调用
                this.successCallback = successCb // 存储成功的回调
                this.failCallback = failCb // 存储失败的回调
            }
        }
    }
    
    const promise = new MyPromise((resolve, reject) => {
        setTimeout(() => {
            // resolve('success')
            reject('fail')
        }, 1500)
    });
    
    promise.then(val => {
        console.log(val)
    }, reason => {
        console.log(reason)
    })
    

    实现Promise then方法被多次调用

    1. Promise的then方法是可以被多次调用的。
    2. 下面示例有三个then的回调,如果是同步回调,那么直接返回当前的值就可以。
    3. 如果是异步回调,那么需要用不同的值保存成功失败的回调,因为互不相同。
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            executor(this.resolve, this.reject)
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while(this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()(this.successData)
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while(this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()(this.failReason)
            }
        }
        then(successCb, failCb) {
            // 判断状态
            if (this.status === FULFILLED) { // 同步调用
                successCb(this.successData) // 调用成功回调,把值返回
            } else if (this.status === REJECTED) { // 同步调用
                failCb(this.failReason) // 调用失败回调,把原因返回
            } else { // 异步调用
                this.successCallback.push(successCb) // 存储成功的回调
                this.failCallback.push(failCb) // 存储失败的回调
            }
        }
    }
    

    测试示例:

    const promise = new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
            // reject('fail')
        }, 1500)
    });
    
    promise.then(val => {
        console.log(val, 11)
    }, reason => {
        console.log(reason, 11)
    })
    
    promise.then(val => {
        console.log(val, 22)
    }, reason => {
        console.log(reason, 22)
    })
    
    promise.then(val => {
        console.log(val, 33)
    }, reason => {
        console.log(reason, 33)
    })
    

    实现Promise then方法的链式调用

    1. Promise的then方法是可以被链式调用,后面then方法的回调函数参数值是上一个then方法回调函数的返回值。
    2. 其中then方法回调函数参数传递包含两种情况:1.参数为普通值 2.参数为另一个promise对象
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            executor(this.resolve, this.reject)
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()(this.successData)
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()(this.failReason)
            }
        }
        then(successCb, failCb) {
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    const s = successCb(this.successData) // 调用成功回调,把值返回
                    // 判断 p 是普通值还是promise对象
                    // 如果是普通值则直接调用resolve
                    // 如果是promise对象,则根据promise对象返回结果决定调用resolve还是reject
                    parsePromiseStatus(s, resolve, reject)
                } else if (this.status === REJECTED) { // 同步调用
                    const f = failCb(this.failReason) // 调用失败回调,把原因返回
                    parsePromiseStatus(f, resolve, reject)
                } else { // 异步调用
                    this.successCallback.push(successCb) // 存储成功的回调
                    this.failCallback.push(failCb) // 存储失败的回调
                }
            })
            return promise
        }
    }
    function parsePromiseStatus(p, resolve, reject) {
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    const promise = new MyPromise((resolve, reject) => {
        resolve('success') // 目前这里只处理了同步的问题
    });
    
    function anther(n) {
        return new MyPromise((resolve, reject) => {
            resolve('anther' + (n || ''))
        })
    }
    
    const p = promise.then(val => {
        console.log('val: ', val)
        // return '2222'
        return anther()
    }, reason => {
        console.log('reason', reason)
        return anther(2)
    }).then(val => {
        console.log('val2: ', val)
    }, reason => {
        console.log('reason2: ', reason)
    })
    

    then方法链式调用识别返回promise对象自身

    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            executor(this.resolve, this.reject)
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()(this.successData)
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()(this.failReason)
            }
        }
        then(successCb, failCb) {
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => { // 使用setTimeout的原因:不使用的话此时方法没执行完毕,不能得到返回值promise
                        const p = successCb(this.successData) // 调用成功回调,把值返回
                        // 判断 p 是普通值还是promise对象
                        // 如果是普通值则直接调用resolve
                        // 如果是promise对象,则根据promise对象返回结果决定调用resolve还是reject
                        parsePromiseStatus(promise, p, resolve, reject)
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    failCb(this.failReason) // 调用失败回调,把原因返回
                } else { // 异步调用
                    this.successCallback.push(successCb) // 存储成功的回调
                    this.failCallback.push(failCb) // 存储失败的回调
                }
            })
            return promise
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    const promise = new MyPromise((resolve, reject) => {
        resolve('success')
    });
    
    const p = promise.then(val => {
        console.log(val, 'resolved')
        return p
    }, reason => {
        console.log(reason, 'rejected')
    })
    
    p.then(val => {
        console.log(val, 22)
    }, reason => {
        console.log(reason.message)
    })
    

    错误捕获

    分为两种:1.执行器的错误捕获 2.then执行的时候错误捕获

    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()(this.successData)
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()(this.failReason)
            }
        }
        then(successCb, failCb) {
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(successCb) // 存储成功的回调
                    this.failCallback.push(failCb) // 存储失败的回调
                }
            })
            return promise
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    const promise = new MyPromise((resolve, reject) => {
        reject('success')
        // throw new Error('executor error')
    });
    
    promise.then(val => {
        console.log(val, 'resolved')
    }, reason => {
        console.log(reason, 'rejected')
        throw new Error('then method error')
    }).then(val => {
        console.log(val, 'then2')
    }, reason => {
        console.log(reason.message)
    })
    

    异步状态下链式调用——promise异步调用resolve或者reject

    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()()
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()()
            }
        }
        then(successCb, failCb) {
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = successCb(this.successData)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储成功的回调
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = failCb(this.failReason)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储失败的回调
                }
            })
            return promise
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    
    

    测试示例:

    const promise = new MyPromise((resolve, reject) => {
        setTimeout(() => {
            resolve('success')
        }, 1000)
    });
    
    promise.then(val => {
        console.log(val, 'resolved')
        return 'xxx'
    }, reason => {
        console.log(reason, 'rejected')
    }).then(val => {
        console.log(val, 'then2')
    }, reason => {
        console.log(reason.message)
    })
    

    将then方法的参数变为可选参数

    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()()
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()()
            }
        }
        then(successCb, failCb) {
            successCb = successCb || (value => value) // 有回调使用回调,没回调赋值一个函数
            failCb = failCb || (reason => { throw reason })
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = successCb(this.successData)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储成功的回调
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = failCb(this.failReason)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储失败的回调
                }
            })
            return promise
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    const promise = new MyPromise((resolve, reject) => {
            // resolve('success')
            reject('fail')
    });
    
    promise.then().then().then(val => {
        console.log('resolved: ', val)
    }, reason => {
        console.log('rejected: ', reason)
    })
    

    Promise.all方法的实现

    1. all方法接收一个数组,数组的每个元素可以是普通值也可以是promise对象
    2. 数组中元素的顺序就是得到结果的顺序
    3. 如果数组中所有值是成功的,那么then里面函数就作为成功回调,如果有一个值是失败的,那么then里面函数就作为失败回调
    4. all方法由类直接调用,那么all肯定是类的静态方法
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()()
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()()
            }
        }
        then(successCb, failCb) {
            successCb = successCb || (value => value) // 有回调使用回调,没回调赋值一个函数
            failCb = failCb || (reason => { throw reason })
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = successCb(this.successData)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储成功的回调
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = failCb(this.failReason)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储失败的回调
                }
            })
            return promise
        }
        static all(arr) {
            const result = []
            let count = 0
            return new MyPromise((resolve, reject) => {
                function addArrayEle(key, value) {
                    result[key] = value
                    count++
                    // 计数器和数组长度相同,表明所有元素执行完毕,可以输出结果
                    if (count === arr.length) {
                        resolve(result)
                    }
                }
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => addArrayEle(i, value), reason => reject(reason))
                    } else {
                        // 普通值
                        addArrayEle(i, current)
                    }
                }
            })
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    function p1() {
        return new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve('p1')
            }, 2000)
        })
    }
    
    function p2() {
        return new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve('p2')
            }, 1000)
        })
    }
    
    MyPromise.all(['a', 'b', p1(), 'c', p2()]).then(val => {
        console.log('val: ', val) // ["a", "b", "p1", "c", "p2"]
    })
    

    Promise.race方法的实现

    1. race方法接收一个数组,每个元素可以是普通值也可以是promise对象
    2. 当存在普通值时,立即返回该值;当所有元素均为promise对象时,如果有一个实例状态改变,就进入该状态且不可改变
    3. 这里所有的promise实例为竞争关系,只选择第一个进入改变状态的promise值或者普通值
    4. race方法由类直接调用,那么all肯定是类的静态方法
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()()
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()()
            }
        }
        then(successCb, failCb) {
            successCb = successCb || (value => value) // 有回调使用回调,没回调赋值一个函数
            failCb = failCb || (reason => { throw reason })
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = successCb(this.successData)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储成功的回调
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = failCb(this.failReason)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储失败的回调
                }
            })
            return promise
        }
        static all(arr) {
            const result = []
            let count = 0
            return new MyPromise((resolve, reject) => {
                function addArrayEle(key, value) {
                    result[key] = value
                    count++
                    // 计数器和数组长度相同,表明所有元素执行完毕,可以输出结果
                    if (count === arr.length) {
                        resolve(result)
                    }
                }
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => addArrayEle(i, value), reason => reject(reason))
                    } else {
                        // 普通值
                        addArrayEle(i, current)
                    }
                }
            })
        }
        static race(arr) {
            return new MyPromise((resolve, reject) => {
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => resolve(value), reason => reject(reason))
                    } else {
                        resolve(current)
                    }
                }
            })
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    function p1() {
        return new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve('p1')
            }, 3000)
        })
    }
    
    function p2() {
        return new MyPromise((resolve, reject) => {
            setTimeout(() => {
                reject('p2')
            }, 1000)
        })
    }
    
    MyPromise.race(['b', p1(), 'a', p2()]).then(val => {
        console.log('val: ', val); // val: b
    }, reason => {
        console.log('reason: ', reason)
    })
    

    Promise.resolve方法的实现

    1. 如果参数是一个promise对象,则直接返回;如果是一个值,则生成一个promise对象把值返回
    2. resolve是类的一个静态方法
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()()
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()()
            }
        }
        then(successCb, failCb) {
            successCb = successCb || (value => value) // 有回调使用回调,没回调赋值一个函数
            failCb = failCb || (reason => { throw reason })
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = successCb(this.successData)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储成功的回调
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = failCb(this.failReason)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储失败的回调
                }
            })
            return promise
        }
        static all(arr) {
            const result = []
            let count = 0
            return new MyPromise((resolve, reject) => {
                function addArrayEle(key, value) {
                    result[key] = value
                    count++
                    // 计数器和数组长度相同,表明所有元素执行完毕,可以输出结果
                    if (count === arr.length) {
                        resolve(result)
                    }
                }
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => addArrayEle(i, value), reason => reject(reason))
                    } else {
                        // 普通值
                        addArrayEle(i, current)
                    }
                }
            })
        }
        static race(arr) {
            return new MyPromise((resolve, reject) => {
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => resolve(value), reason => reject(reason))
                    } else {
                        resolve(current)
                    }
                }
            })
        }
        static resolve(value) {
            if(value instanceof MyPromise) {
                return value
            }
            return new MyPromise(resolve => resolve(value))
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    function p1() {
        return new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve('p1')
            }, 2000)
        })
    }
    
    MyPromise.resolve(2000).then(val => {
        console.log('val: ', val) // 2000
    })
    
    MyPromise.resolve(p1()).then(val => {
        console.log('val: ', val) // 'p1'
    })
    

    Promise.reject方法的实现

    1. 如果参数是一个promise对象,则直接返回;如果是一个值,则生成一个promise对象把值返回
    2. resolve是类的一个静态方法
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()()
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()()
            }
        }
        then(successCb, failCb) {
            successCb = successCb || (value => value) // 有回调使用回调,没回调赋值一个函数
            failCb = failCb || (reason => { throw reason })
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = successCb(this.successData)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储成功的回调
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = failCb(this.failReason)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储失败的回调
                }
            })
            return promise
        }
        static all(arr) {
            const result = []
            let count = 0
            return new MyPromise((resolve, reject) => {
                function addArrayEle(key, value) {
                    result[key] = value
                    count++
                    // 计数器和数组长度相同,表明所有元素执行完毕,可以输出结果
                    if (count === arr.length) {
                        resolve(result)
                    }
                }
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => addArrayEle(i, value), reason => reject(reason))
                    } else {
                        // 普通值
                        addArrayEle(i, current)
                    }
                }
            })
        }
        static race(arr) {
            return new MyPromise((resolve, reject) => {
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => resolve(value), reason => reject(reason))
                    } else {
                        resolve(current)
                    }
                }
            })
        }
        static resolve(value) {
            if (value instanceof MyPromise) {
                return value
            }
            return new MyPromise(resolve => resolve(value))
        }
        static reject(reason) {
            return new MyPromise((resolve, reject) => reject(reason))
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    MyPromise.reject(1234).then(null, val => {
        console.log('val: ', val) // val: 123
    })
    

    finally方法的实现

    1. 在原型对象上使用,所以不是静态方法
    2. 无论当前状态是成功还是失败,finally都会执行
    3. 可以在finally方法之后调用then方法得到结果
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()()
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()()
            }
        }
        then(successCb, failCb) {
            successCb = successCb || (value => value) // 有回调使用回调,没回调赋值一个函数
            failCb = failCb || (reason => { throw reason })
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = successCb(this.successData)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储成功的回调
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = failCb(this.failReason)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储失败的回调
                }
            })
            return promise
        }
        finally(callback) {
            return this.then(value => {
                return MyPromise.resolve(callback()).then(() => value)
            }, reason => {
                return MyPromise.resolve(callback()).then(() => { throw reason })
            })
        }
        static all(arr) {
            const result = []
            let count = 0
            return new MyPromise((resolve, reject) => {
                function addArrayEle(key, value) {
                    result[key] = value
                    count++
                    // 计数器和数组长度相同,表明所有元素执行完毕,可以输出结果
                    if (count === arr.length) {
                        resolve(result)
                    }
                }
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => addArrayEle(i, value), reason => reject(reason))
                    } else {
                        // 普通值
                        addArrayEle(i, current)
                    }
                }
            })
        }
        static race(arr) {
            return new MyPromise((resolve, reject) => {
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => resolve(value), reason => reject(reason))
                    } else {
                        resolve(current)
                    }
                }
            })
        }
        static resolve(value) {
            if (value instanceof MyPromise) {
                return value
            }
            return new MyPromise(resolve => resolve(value))
        }
        static reject(reason) {
            return new MyPromise((resolve, reject) => reject(reason))
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    function p1() {
        return new MyPromise((resolve, reject) => {
            setTimeout(() => {
                resolve('p1')
            }, 2000)
        })
    }
    
    function p2() {
        return new MyPromise((resolve, reject) => {
            reject('p1')
        })
    }
    
    p2().finally(() => {
        console.log('finally')
        return p1()
    }).then(val => {
        console.log('resolve: ', val)
    }, reason => {
        console.log('reject: ', reason)
    })
    

    catch方法的实现

    1. 在原型对象上使用,所以不是静态方法
    2. 直接调用then方法,第一个参数传递undefined,第二个参数传递reason
    const PENDING = 'pending'; // 等待
    const FULFILLED = 'fulfilled'; // 成功
    const REJECTED = 'rejected'; // 失败
    
    class MyPromise {
        constructor(executor) {
            try {
                executor(this.resolve, this.reject)
            } catch (e) {
                this.reject(e)
            }
        }
        status = PENDING // 实例属性用来表示promise状态
        successData = undefined // 存储成功后resolve传递的参数
        failReason = undefined // 存储失败后reject传递的参数
        successCallback = [] // 存储成功的回调函数
        failCallback = [] // 存储失败的回调函数
        resolve = (val) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = FULFILLED // 将状态改为成功
            this.successData = val // 存储成功之后的值
            while (this.successCallback.length) { // 异步逻辑下调用成功的回调
                this.successCallback.shift()()
            }
        }
        reject = (reason) => {
            if (this.status !== PENDING) return // 状态为pending时才可继续向下执行
            this.status = REJECTED // 将状态改为失败
            this.failReason = reason // 存储失败之后的值
            while (this.failCallback.length) { // 异步逻辑下调用失败的回调
                this.failCallback.shift()()
            }
        }
        then(successCb, failCb) {
            successCb = successCb || (value => value) // 有回调使用回调,没回调赋值一个函数
            failCb = failCb || (reason => { throw reason })
            const promise = new MyPromise((resolve, reject) => {
                // 判断状态
                if (this.status === FULFILLED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = successCb(this.successData)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else if (this.status === REJECTED) { // 同步调用
                    setTimeout(() => {
                        try {
                            const p = failCb(this.failReason)
                            parsePromiseStatus(promise, p, resolve, reject)
                        } catch (e) {
                            reject(e)
                        }
                    }, 0)
                } else { // 异步调用
                    this.successCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = successCb(this.successData)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储成功的回调
                    this.failCallback.push(() => {
                        setTimeout(() => {
                            try {
                                const p = failCb(this.failReason)
                                parsePromiseStatus(promise, p, resolve, reject)
                            } catch (e) {
                                reject(e)
                            }
                        }, 0)
                    }) // 存储失败的回调
                }
            })
            return promise
        }
        finally(callback) {
            return this.then(value => {
                return MyPromise.resolve(callback()).then(() => value)
            }, reason => {
                return MyPromise.resolve(callback()).then(() => { throw reason })
            })
        }
        catch(failCallback) {
            return this.then(undefined, failCallback);
        }
        static all(arr) {
            const result = []
            let count = 0
            return new MyPromise((resolve, reject) => {
                function addArrayEle(key, value) {
                    result[key] = value
                    count++
                    // 计数器和数组长度相同,表明所有元素执行完毕,可以输出结果
                    if (count === arr.length) {
                        resolve(result)
                    }
                }
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => addArrayEle(i, value), reason => reject(reason))
                    } else {
                        // 普通值
                        addArrayEle(i, current)
                    }
                }
            })
        }
        static race(arr) {
            return new MyPromise((resolve, reject) => {
                for (let i = 0; i < arr.length; i++) {
                    let current = arr[i]
                    if (current instanceof MyPromise) {
                        // promise对象
                        current.then(value => resolve(value), reason => reject(reason))
                    } else {
                        resolve(current)
                    }
                }
            })
        }
        static resolve(value) {
            if (value instanceof MyPromise) {
                return value
            }
            return new MyPromise(resolve => resolve(value))
        }
        static reject(reason) {
            return new MyPromise((resolve, reject) => reject(reason))
        }
    }
    
    function parsePromiseStatus(promise, p, resolve, reject) {
        if (promise === p) {
            return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
        }
        if (p instanceof MyPromise) {
            p.then(resolve, reject)
        } else {
            resolve(p)
        }
    }
    

    测试示例:

    function p2() {
        return new MyPromise((resolve, reject) => {
            reject('p2 failed')
        })
    }
    
    p2().then(val => {
        console.log('resolve: ', val)
    }).catch(reason => {
        console.log('fail: ', reason) // fail:  p2 failed
    })
    

    起源地下载网 » Promise规范解读及简易实现

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元