完整的Promise实现

Promise简介

一个Promise 对象代表一个在这个 promise 被创建出来时不一定已知的值。它让您能够把异步操作最终的成功返回值或者失败原因和相应的处理程序关联起来。 这样使得异步方法可以像同步方法那样返回值:异步方法并不会立即返回最终的值,而是会返回一个 promise ,以便在未来某个时候把值交给使用者。

一个 Promise 必然处于以下几种状态之一:

  • 待定(pending) : 初始状态,既没有被兑现,也没有被拒绝。
  • 已兑现(fulfilled) : 意味着操作成功完成。
  • 已拒绝(rejected) : 意味着操作失败。

待定状态的 Promise 对象要么会通过一个值被兑现(fulfilled) ,要么会通过一个原因(错误) 被拒绝(rejected) 。当这些情况之一发生时,我们用 promise 的 then 方法排列起来的相关处理程序就会被调用。如果 promise 在一个相应的处理程序被绑定时就已经被兑现或被拒绝了,那么这个处理程序就会被调用,因此在完成异步操作和绑定处理方法之间不会存在竞争状态。

因为 Promsie的then、catch和finally方法返回的是 promise, 所以它们可以被链式调用。

promises.png

Promise实例的方法(设promise为Promise的实例)

promise.then(onFulfilled,onRejected)

onFulfilled(可选):将在promise的状态变成fulfilled时调用,参数为promise成功的结果。如果onFulfilled的返回值不是一个promise,那么其返回值将作为下一个then的onFulfilled参数;如果onFulfilled的返回值是一个成功的promise,那么这个promise的成功结果将作为下一个then的onFulfilled参数;如果onFulfilled的返回值是一个失败的promise,那么这个promise的失败原因将作为下一个then的onRejected参数。

onRejected(可选):将在promise的状态变成rejected时调用,参数为promise失败的原因。其返回值的行为与onFulfilled的返回值一致。

promise.catch(onRejected)

onRejected在promise的状态变成rejected时调用,参数为失败原因。其返回值的行为与onFulfilled的返回值一致。

promise.finally(onFinally)

在 promise 结束时,无论结果是 fulfilled 或者是 rejected,都会执行onFinally。这样避免了同样的语句在then和catch里各写一次的情况。

Promise的静态方法

Promise.all(iterable)

这个方法返回一个新的 promise 对象,该 promise 对象在 iterable 参数对象里所有的 promise 对象都成功的时候才会触发成功,一旦有任何一个 iterable 里面的 promise 对象失败则立即触发该 promise 对象的失败。这个新的 promise 对象在触发成功状态以后,会把一个包含 iterable 里所有 promise 返回值的数组作为成功回调的返回值,顺序跟 iterable 的顺序保持一致;如果这个新的 promise 对象触发了失败状态,它会把 iterable 里第一个触发失败的 promise 对象的错误信息作为它的失败错误信息。Promise.all 方法常被用于处理多个 promise 对象的状态集合。

Promise.allSettled(iterable)

等到所有 promises 都已敲定(settled)(每个 promise 都已兑现(fulfilled)或已拒绝(rejected))。返回一个 promise,该 promise 在所有 promise 完成后完成。并带有一个对象数组,每个对象对应每个 promise 的结果。

Promise.any(iterable)

接收一个 Promise 对象的集合,当其中的一个 promise 成功,就返回那个成功的 promise 的值。

Promise.race(iterable)

当 iterable 参数里的任意一个子 promise 被成功或失败后,父 promise 马上也会用子 promise 的成功返回值或失败详情作为参数调用父 promise 绑定的相应句柄,并返回该 promise 对象。

Promise.resolve(value)

返回一个状态由给定 value 决定的 Promise 对象。如果该值是 thenable(即,带有 then 方法的对象),返回的 Promise 对象的最终状态由 then 方法执行决定;否则的话(该 value 为空,基本类型或者不带 then 方法的对象),返回的 Promise 对象状态为 fulfilled,并且将该 value 传递给对应的 then 方法。通常而言,如果您不知道一个值是否是 Promise 对象,使用 Promise.resolve(value) 来返回一个 Promise 对象,这样就能将该 value 以 Promise 对象形式使用。

Promise.reject(reason)

返回一个状态为失败的 Promise 对象,并将给定的失败信息传递给对应的处理方法。

Promise的实现

实现构造函数

首先,Promise构造函数的参数是一个具有两个函数作为参数的函数,Promise的初始状态为pending

class Promise {
        constructor(executor) {
        //一个promise的状态只能是pending,fulfilled或者rejected之一
            //初始状态为pending,且状态只能由pending变成fulfilled或者rejected
            this.state = 'pending';
            //保存promise成功时的值
            this.value = null;
            //保存promise失败时的值
            this.reason = null;
            //调用resolve代表成功
            let resolve = (value) => {
                if (this.state === 'pending') {
                    this.state = 'fulfilled';//成功时状态变更为fulfilled
                    this.value = value;
                }
            };
            //调用reject代表失败
            let reject = (reason) => {
                if (this.state === 'pending') {
                    this.state = 'rejected';//失败时状态变更为rejected
                    this.reason = reason;
                }
            };
        //实例化一个promise时,构造函数的参数会立即执行,且这个参数是一个带有两个参数的函数
            //构造函数内部出错时状态变更为rejected
            try {
                executor(resolve, reject);
            } catch (e) {
                reject(e);
            }
        }
    }
实现then的基础(还未涉及微任务和链式调用)

onFulfilledArr和onRejectedArr分别保存then中注册的onFulfilled和onRejected,在Promise状态改变时执行其保存的函数。这里使用的发布/订阅模式,onFulfilled和onRejected相当于订阅者,resolve和reject相当于发布者。

    class Promise {
        constructor(executor) {
            //一个promise的状态只能是pending,fulfilled或者rejected之一
            //初始状态为pending,且状态只能由pending变成fulfilled或者rejected
            this.state = 'pending';
            //保存promise成功时的值
            this.value = null;
            //保存promise失败时的值
            this.reason = null;
            //保存成功的回调函数,用数组保存(一个promise实例可能有多个then)
            this.onFulfilledArr = [];
            //保存失败的回调函数
            this.onRejectedArr = [];
            //调用resolve代表成功
            let resolve = (value) => {
                //状态只能由pending变成fulfilled或者rejected
                if (this.state === 'pending') {
                    this.state = 'fulfilled';//成功时状态变更为fulfilled
                    this.value = value;
                    //执行then中注册的成功回调
                    this.onFulfilledArr.forEach(func => {
                        func();
                    });
                }
            };
            //调用reject代表失败
            let reject = (reason) => {
                //状态只能由pending变成fulfilled或者rejected
                if (this.state === 'pending') {
                    this.state = 'rejected';//失败时状态变更为rejected
                    this.reason = reason;
                    //执行then中注册的失败回调
                    this.onRejectedArr.forEach(func => {
                        func();
                    });
                }
            };
            //实例化一个promise时,构造函数的参数会立即执行,且这个参数是一个带有两个参数的函数
            //构造函数内部出错时状态变更为rejected
            try {
                executor(resolve, reject);
            } catch (e) {
                reject(e);
            }
        }

        //then方法,onFulfilled和onRejected分别表示成功和失败回调
        then(onFulfilled, onRejected) {
            //还在等待
            if (this.state === 'pending') {
                //需要保存回调方法,在状态改变后再执行
                this.onFulfilledArr.push(() => {
                    if (typeof onFulfilled === 'function') {
                        onFulfilled(this.value);//将resolve的参数传给onFulfilled
                    }
                })
                this.onRejectedArr.push(() => {
                    if (typeof onRejected === 'function') {
                        onRejected(this.reason);//将resolve的参数传给onFulfilled
                    }
                })
            } else {
                //状态已经改变了
                //成功
                if (this.state === 'fulfilled') {
                    if (typeof onFulfilled === 'function') {
                        onFulfilled(this.value);
                    }
                }
                //失败
                if (this.state === 'rejected') {
                    if (typeof onRejected === 'function') {
                        onRejected(this.reason);
                    }
                }
            }
        }
    }
实现链式调用

链式调用的关键在于then方法的返回值也是一个Promise实例,个人认为Promise的核心就是then方法,将then理解透彻了,其他的实例和静态方法就很好

    class Promise {
        constructor(executor) {
            //一个promise的状态只能是pending,fulfilled或者rejected之一
            //初始状态为pending,且状态只能由pending变成fulfilled或者rejected
            this.state = 'pending';
            //保存promise成功时的值
            this.value = null;
            //保存promise失败时的值
            this.reason = null;
            //保存成功的回调函数,用数组保存(一个promise实例可能有多个then)
            this.onFulfilledArr = [];
            //保存失败的回调函数
            this.onRejectedArr = [];
            //调用resolve代表成功
            let resolve = (value) => {
                //状态只能由pending变成fulfilled或者rejected
                if (this.state === 'pending') {
                    this.state = 'fulfilled';//成功时状态变更为fulfilled
                    this.value = value;
                    //执行then中注册的成功回调
                    this.onFulfilledArr.forEach(func => {
                        func();
                    })
                }
            };
            //调用reject代表失败
            let reject = (reason) => {
                //状态只能由pending变成fulfilled或者rejected
                if (this.state === 'pending') {
                    this.state = 'rejected';//失败时状态变更为rejected
                    this.reason = reason;
                    //执行then中注册的失败回调
                    this.onRejectedArr.forEach(func => {
                        func();
                    })
                }
            };
            //实例化一个promise时,构造函数的参数会立即执行,且这个参数是一个带有两个参数的函数
            //构造函数内部出错时状态变更为rejected
            try {
                executor(resolve, reject);
            } catch (e) {
                reject(e);
            }
        }

        //then方法,onFulfilled和onRejected分别表示成功和失败回调
        //then是Promise实例的方法,then可以调用then,说明then的返回值也是一个Promise实例
        then(onFulfilled, onRejected) {
            //then内部返回的promise
            let promise = new Promise((resolve, reject) => {
                //还在等待(异步)
                if (this.state === 'pending') {
                    //需要保存回调方法,在状态改变后再执行
                    this.onFulfilledArr.push(() => {
                        //这使用异步是为了能够拿到promise实例,在构造函数中直接拿会报错,queueMicrotask在node环境中可以使用process.nextTick代替
                        queueMicrotask(() => {
                            try {
                                if (typeof onFulfilled === 'function') {
                                    let x = onFulfilled(this.value);
                                    //成功回调有返回值时才传给下一个then
                                    resolvePromise(promise, x, resolve, reject);
                                } else {
                                    resolve(this.value);//如果没有写成功回调,那么将成功的回调的参数传给下一个then的成功回调
                                }
                            } catch (e) {
                                reject(e);
                            }
                        })
                        //try catch无法捕获异步中的错误,因此不这样写
                        // try {
                        //     if (typeof onFulfilled === 'function') {
                        //         let x = onFulfilled(this.value);
                        //         //成功回调有返回值时才传给下一个then
                        //         queueMicrotask(()=>{
                        //             resolvePromise(promise, x, resolve, reject);
                        //         })
                        //     } else {
                        //         resolve(this.value);//如果没有写成功回调,那么将成功的回调的参数传给下一个then的成功回调
                        //     }
                        // } catch (e) {
                        //     reject(e);
                        // }
                    })
                    this.onRejectedArr.push(() => {
                        queueMicrotask(() => {
                            try {
                                if (typeof onRejected === 'function') {
                                    let x = onRejected(this.reason);
                                    resolvePromise(promise, x, resolve, reject);
                                } else {
                                    reject(this.reason);//如果没有写失败回调,那么将失败的回调的参数传给下一个then的失败回调
                                }
                            } catch (e) {
                                reject(e);
                            }
                        })
                    })
                } else {
                    //状态已经改变了
                    //成功
                    if (this.state === 'fulfilled') {
                        queueMicrotask(() => {
                            try {
                                if (typeof onFulfilled === 'function') {
                                    let x = onFulfilled(this.value);
                                    resolvePromise(promise, x, resolve, reject);
                                } else {
                                    resolve(this.value);
                                }
                            } catch (e) {
                                reject(e);
                            }
                        })
                    }
                    //失败
                    if (this.state === 'rejected') {
                        queueMicrotask(() => {
                            try {
                                if (typeof onRejected === 'function') {
                                    let x = onRejected(this.reason);
                                    resolvePromise(promise, x, resolve, reject);
                                } else {
                                    reject(this.reason);
                                }
                            } catch (e) {
                                reject(e);
                            }
                        })
                    }
                }
            })
            return promise;
        }
    }

    //then内部的promise是如何将返回值传递给下一个then的
    let resolvePromise = function (promise, x, resolve, reject) {
        if (x === promise) {//防止出现自己等待自己的情况
            //这种情况下就会报错
            // let promise=new Promise((resolve,reject)=>{
            //     resolve('aa');
            // })
            // let a=promise.then(res=>{
            //     return a;
            // })
            let err = new TypeError('Chaining cycle detected for promise #<Promise>');
            console.error(err);
        } else {
            if (x instanceof Promise) {
                //当x是一个Promise实例时,将then内部返回的promise的resolve和reject注册为x的成功和失败回调
                //当x的状态改变时,x调用自己的resolve和reject也就是调用了then内部的resolve和reject
                x.then(resolve, reject);
            } else {
                //x只是一个普通对象时直接传给下一个then的成功回调作为参数
                //then中失败回调的返回值也会传给下一个then的成功回调作为参数
                resolve(x);
            }
        }
    }
Promise实例的catch和finally方法

catch其实就是只有失败回调的then方法,finally的返回值也是一个Promise实例

        // catch 是一个只有失败回调的then函数
        catch(onRejected) {
            return this.then(null, onRejected);
        }

        //finally()方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。
        //这避免了同样的语句需要在then()和catch()中各写一次的情况。
        finally(onFinally) {
            return new Promise((resolve, reject) => {
                this.then(res => {
                    try {
                        onFinally && onFinally();
                        resolve(res);//将结果传给finally的then
                    } catch (e) {
                        reject(e);
                    }
                }, err => {
                    try {
                        onFinally && onFinally();
                        reject(err);
                    } catch (e) {
                        reject(e);
                    }
                })
            })
        }
Promise的静态方法

Promise静态方法的作用在简介里,代码注释中也有,这里不再简述,直接上Promise的完整代码

    class Promise {
        constructor(executor) {
            //一个promise的状态只能是pending,fulfilled或者rejected之一
            //初始状态为pending,且状态只能由pending变成fulfilled或者rejected
            this.state = 'pending';
            //保存promise成功时的值
            this.value = null;
            //保存promise失败时的值
            this.reason = null;
            //保存成功的回调函数,用数组保存(一个promise实例可能有多个then)
            this.onFulfilledArr = [];
            //保存失败的回调函数
            this.onRejectedArr = [];
            //调用resolve代表成功
            let resolve = (value) => {
                //状态只能由pending变成fulfilled或者rejected
                if (this.state === 'pending') {
                    this.state = 'fulfilled';//成功时状态变更为fulfilled
                    this.value = value;
                    //执行then中注册的成功回调
                    this.onFulfilledArr.forEach(func => {
                        func();
                    })
                }
            };
            //调用reject代表失败
            let reject = (reason) => {
                //状态只能由pending变成fulfilled或者rejected
                if (this.state === 'pending') {
                    this.state = 'rejected';//失败时状态变更为rejected
                    this.reason = reason;
                    //执行then中注册的失败回调
                    this.onRejectedArr.forEach(func => {
                        func();
                    })
                }
            };
            //实例化一个promise时,构造函数的参数会立即执行,且这个参数是一个带有两个参数的函数
            //构造函数内部出错时状态变更为rejected
            try {
                executor(resolve, reject);
            } catch (e) {
                reject(e);
            }
        }

        //then方法,onFulfilled和onRejected分别表示成功和失败回调
        //then是Promise实例的方法,then可以调用then,说明then的返回值也是一个Promise实例
        then(onFulfilled, onRejected) {
            //then内部返回的promise
            let promise = new Promise((resolve, reject) => {
                //还在等待(异步)
                if (this.state === 'pending') {
                    //需要保存回调方法,在状态改变后再执行
                    this.onFulfilledArr.push(() => {
                        //这使用异步是为了能够拿到promise实例,在构造函数中直接拿会报错,queueMicrotask在node环境中可以使用process.nextTick代替
                        queueMicrotask(() => {
                            try {
                                if (typeof onFulfilled === 'function') {
                                    let x = onFulfilled(this.value);
                                    //成功回调有返回值时才传给下一个then
                                    resolvePromise(promise, x, resolve, reject);
                                } else {
                                    resolve(this.value);//如果没有写成功回调,那么将成功的回调的参数传给下一个then的成功回调
                                }
                            } catch (e) {
                                reject(e);
                            }
                        })
                        //try catch无法捕获异步中的错误,因此不这样写
                        // try {
                        //     if (typeof onFulfilled === 'function') {
                        //         let x = onFulfilled(this.value);
                        //         //成功回调有返回值时才传给下一个then
                        //         queueMicrotask(()=>{
                        //             resolvePromise(promise, x, resolve, reject);
                        //         })
                        //     } else {
                        //         resolve(this.value);//如果没有写成功回调,那么将成功的回调的参数传给下一个then的成功回调
                        //     }
                        // } catch (e) {
                        //     reject(e);
                        // }
                    })
                    this.onRejectedArr.push(() => {
                        queueMicrotask(() => {
                            try {
                                if (typeof onRejected === 'function') {
                                    let x = onRejected(this.reason);
                                    resolvePromise(promise, x, resolve, reject);
                                } else {
                                    reject(this.reason);//如果没有写失败回调,那么将失败的回调的参数传给下一个then的失败回调
                                }
                            } catch (e) {
                                reject(e);
                            }
                        })
                    })
                } else {
                    //状态已经改变了
                    //成功
                    if (this.state === 'fulfilled') {
                        queueMicrotask(() => {
                            try {
                                if (typeof onFulfilled === 'function') {
                                    let x = onFulfilled(this.value);
                                    resolvePromise(promise, x, resolve, reject);
                                } else {
                                    resolve(this.value);
                                }
                            } catch (e) {
                                reject(e);
                            }
                        })
                    }
                    //失败
                    if (this.state === 'rejected') {
                        queueMicrotask(() => {
                            try {
                                if (typeof onRejected === 'function') {
                                    let x = onRejected(this.reason);
                                    resolvePromise(promise, x, resolve, reject);
                                } else {
                                    reject(this.reason);
                                }
                            } catch (e) {
                                reject(e);
                            }
                        })
                    }
                }
            })
            return promise;
        }

        // catch 是一个只有失败回调的then函数
        catch(onRejected) {
            return this.then(null, onRejected);
        }

        //finally()方法返回一个Promise。在promise结束时,无论结果是fulfilled或者是rejected,都会执行指定的回调函数。这为在Promise是否成功完成后都需要执行的代码提供了一种方式。
        //这避免了同样的语句需要在then()和catch()中各写一次的情况。
        finally(onFinally) {
            return new Promise((resolve, reject) => {
                this.then(res => {
                    try {
                        onFinally && onFinally();
                        resolve(res);//将结果传给finally的then
                    } catch (e) {
                        reject(e);
                    }
                }, err => {
                    try {
                        onFinally && onFinally();
                        reject(err);
                    } catch (e) {
                        reject(e);
                    }
                })
            })
        }


        //静态方法resolve
        //返回一个状态由给定value决定的Promise对象。
        //如果该值是thenable(即,带有then方法的对象),返回的Promise对象的最终状态由then方法执行决定;
        //否则的话(该value为空,基本类型或者不带then方法的对象),返回的Promise对象状态为fulfilled,并且将该value传递给对应的then方法。
        //通常而言,如果您不知道一个值是否是Promise对象,使用Promise.resolve(value) 来返回一个Promise对象,这样就能将该value以Promise对象形式使用。
        static resolve(res) {
            return new Promise((resolve, reject) => {
                if (res && res instanceof Promise) {//如果参数是Promise,那么最终的状态由这个Promise决定
                    res.then(data => {
                        resolve(data);
                    }, err => {
                        reject(err);
                    })
                } else {
                    resolve(res);//如果是普通对象,直接作为成功结果
                }
            })
        }

        //静态方法reject
        //Promise.reject()方法的参数,会原封不动地作为reject的理由,变成后续方法的参数。这一点与Promise.resolve方法不一致。
        static reject(reason) {
            return new Promise((resolve, reject) => {
                reject(reason);
            })
        }

        //静态方法race
        //当iterable参数里的任意一个子promise被成功或失败后,父promise马上也会用子promise的成功返回值或失败详情作为参数调用父promise绑定的相应句柄,并返回该promise对象。
        static race(promises) {
            return new Promise((resolve, reject) => {//返回的promise
                if (!isIterable(promises)) {//promises不是可迭代的对象直接失败
                    let err = new TypeError('object is not iterable (cannot read property Symbol(Symbol.iterator))');
                    reject(err);
                    throw err;
                }
                for (const promise of promises) {//利用Promise状态凝固的特性,返回的promise的状态只会改变一次。
                    // 当数组中的任意一个promise完成时,就会改变返回promise的状态,即使之后数组中其他promise也完成时,返回的promise也不再执行resolve或reject
                    promise.then(res => {
                        resolve(res);
                    }, err => {
                        reject(err);
                    })
                }
            })
        }

        //静态方法all
        //这个方法返回一个新的promise对象,该promise对象在iterable参数对象里所有的promise对象都成功的时候才会触发成功,
        //一旦有任何一个iterable里面的promise对象失败则立即触发该promise对象的失败。
        //这个新的promise对象在触发成功状态以后,会把一个包含iterable里所有promise返回值的数组作为成功回调的返回值,顺序跟iterable的顺序保持一致;
        //如果这个新的promise对象触发了失败状态,它会把iterable里第一个触发失败的promise对象的错误信息作为它的失败错误信息。Promise.all方法常被用于处理多个promise对象的状态集合。
        static all(promises) {
            let resultArr = [];//保存promises的结果
            let count = 0;//已完成的promise数量
            return new Promise((resolve, reject) => {
                if (!isIterable(promises)) {
                    let err = new TypeError('object is not iterable (cannot read property Symbol(Symbol.iterator))');
                    reject(err);
                    throw err;
                }
                for (let i = 0; i < promises.length; i++) {
                    promises[i].then(res => {
                        count++;
                        resultArr[i] = res;//按promises传入顺序保存
                        if (count === promises.length) {//promise已经全部执行完毕了
                            resolve(resultArr);
                        }
                    }, err => {
                        //立即触发失败,利用promise的状态凝固,只会抛出第一个错误
                        reject(err);
                    })
                }
            })
        }

        //静态方法allSettled
        //等到所有promises都已敲定(settled)(每个promise都已兑现(fulfilled)或已拒绝(rejected))。
        //返回一个promise,该promise在所有promise完成后完成。并带有一个对象数组,每个对象对应每个promise的结果。
        static allSettled(promises) {
            let resultArr = [];//保存promises的结果
            let count = 0;//已完成的promise数量
            return new Promise((resolve, reject) => {
                if (!isIterable(promises)) {
                    let err = new TypeError('object is not iterable (cannot read property Symbol(Symbol.iterator))');
                    reject(err);
                    throw err;
                }
                for (let i = 0; i < promises.length; i++) {
                    promises[i].then(res => {
                        count++;
                        resultArr[i] = {
                            status: "fulfilled",
                            value: res,
                        };//按promises传入顺序保存
                        if (count === promises.length) {
                            resolve(resultArr);
                        }
                    }, err => {
                        count++;
                        resultArr[i] = {
                            status: "rejected",
                            value: err,
                        };
                        if (count === promises.length) {
                            resolve(resultArr);
                        }
                    })
                }
            })
        }

        //静态方法any
        //接收一个Promise对象的集合,当其中的一个promise成功,就返回那个成功的promise的值。
        static any(promises) {
            let hasResolve = false;//是否有已经成功的promise
            return new Promise((resolve, reject) => {//返回的promise
                if (!isIterable(promises)) {
                    let err = new TypeError('object is not iterable (cannot read property Symbol(Symbol.iterator))');
                    reject(err);
                    throw err;
                }
                for (const promise of promises) {//利用Promise状态凝固的特性,返回的promise的状态只会改变一次。
                    // 当数组中的任意一个promise完成时,就会改变返回promise的状态,即使之后数组中其他promise也完成时,返回的promise也不再执行resolve或reject
                    promise.then(res => {
                        hasResolve = true;
                        resolve(res);
                    })
                }
                Promise.allSettled(promises).then(res => {
                    //所有promise状态都敲定为失败时
                    if (!hasResolve) {
                        reject('AggregateError: All promises were rejected');
                    }
                })
            })
        }
    }

    //then内部的promise是如何将返回值传递给下一个then的
    let resolvePromise = function (promise, x, resolve, reject) {
        if (x === promise) {//防止出现自己等待自己的情况
            //这种情况下就会报错
            // let promise=new Promise((resolve,reject)=>{
            //     resolve('aa');
            // })
            // let a=promise.then(res=>{
            //     return a;
            // })
            let err = new TypeError('Chaining cycle detected for promise #<Promise>');
            console.error(err);
        } else {
            if (x instanceof Promise) {
                //当x是一个Promise实例时,将then内部返回的promise的resolve和reject注册为x的成功和失败回调
                //当x的状态改变时,x调用自己的resolve和reject也就是调用了then内部的resolve和reject
                x.then(resolve, reject);
            } else {
                //x只是一个普通对象时直接传给下一个then的成功回调作为参数
                //then中失败回调的返回值也会传给下一个then的成功回调作为参数
                resolve(x);
            }
        }
    }

    //判断一个对象是否是可迭代的
    let isIterable = function (obj) {
        return obj != null && typeof obj[Symbol.iterator] === 'function';
    }
ES5版本的实现

为了兼容IE9及以上版本,这里的代码里的微任务queueMicrotask使用宏任务setTimeout代替

function Promise(executor) {
    this.state = 'pending';
    this.value = null;
    this.reason = null;
    this.onFulfilledArr = [];
    this.onRejectedArr = [];
    var self = this;
    var resolve = function (res) {
        if (self.state === 'pending') {
            self.state = 'fulfilled';
            self.value = res;
            for (var i = 0; i < self.onFulfilledArr.length; i++) {
                self.onFulfilledArr[i]();
            }
        }
    }
    //reject方法
    var reject = function (reason) {
        if (self.state === 'pending') {
            self.state = 'rejected';
            self.reason = reason;
            for (var i = 0; i < self.onRejectedArr.length; i++) {
                self.onRejectedArr[i]();
            }
        }
    }
    try {
        executor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}
Promise.prototype.then = function (onFulfilled, onRejected) {
    var self = this;
    var promise = new Promise(function (resolve, reject) {
        if (self.state === 'pending') {
            //成功回调处理
            self.onFulfilledArr.push(function () {
                setTimeout(function () {
                    try {
                        if (typeof onFulfilled === 'function') {
                            var x = onFulfilled(self.value);
                            dealThen(promise, x, resolve, reject);
                        } else {
                            resolve(self.value);
                        }
                    } catch (e) {
                        reject(e);
                    }
                })
            })
            self.onRejectedArr.push(function () {
                setTimeout(function () {
                    try {
                        if (typeof onRejected === 'function') {
                            var x = onRejected(self.reason);
                            dealThen(promise, x, resolve, reject);
                        } else {
                            reject(self.reason);
                        }
                    } catch (e) {
                        reject(e);
                    }
                })
            })
        }
        if (self.state === 'fulfilled') {
            setTimeout(function () {
                try {
                    if (typeof onFulfilled === 'function') {
                        var x = onFulfilled(self.value);
                        dealThen(promise, x, resolve, reject);
                    } else {
                        resolve(self.value);
                    }
                } catch (e) {
                    reject(e);
                }
            })
        }
        if (self.state === 'rejected') {
            setTimeout(function () {
                try {
                    if (typeof onRejected === 'function') {
                        var x = onRejected(self.reason);
                        dealThen(promise, x, resolve, reject);
                    } else {
                        reject(self.reason);
                    }
                } catch (e) {
                    reject(e);
                }
            })
        }
    })
    return promise;
}
Promise.prototype.catch = function (onRejected) {
    return this.then(null, onRejected);
}
Promise.prototype.finally = function (callback) {
    var self = this;
    return new Promise(function (resolve, reject) {
        self.then(function (res) {
            try {
                callback();
                resolve(res)
            } catch (e) {
                reject(e);
            }
        }, function (err) {
            try {
                callback();
                reject(err)
            } catch (e) {
                reject(e);
            }
        })
    })
}
Promise.resolve = function (res) {
    return new Promise(function (resolve, reject) {
        if (res && res.__proto__.constructor === Promise) {
            res.then(function (data) {
                resolve(data);
            }, function (err) {
                reject(err);
            })
        } else {
            resolve(res);
        }
    })
}
Promise.reject = function (reason) {
    return new Promise(function (resolve, reject) {
        reject(reason);
    })
}
Promise.race = function (promises) {
    return new Promise(function (resolve, reject) {
        if (promises.__proto__.constructor !== Array) {
            var err = new TypeError('object is not iterable (cannot read property Symbol(Symbol.iterator))');
            reject(err);
            throw err;
        }
        for (var i = 0; i < promises.length; i++) {
            promises[i].then(function (res) {
                resolve(res);
            }, function (err) {
                reject(err);
            })
        }
    })
}
Promise.all = function (promises) {
    var resultArr = [];
    var count = 0;
    return new Promise(function (resolve, reject) {
        if (promises.__proto__.constructor !== Array) {
            var err = new TypeError('object is not iterable (cannot read property Symbol(Symbol.iterator))');
            reject(err);
            throw err;
        }
        for (var i = 0; i < promises.length; i++) {
            (function (i) {
                promises[i].then(function (res) {
                    count++;
                    resultArr[i] = res;
                    if (count === promises.length) {
                        resolve(resultArr);
                    }
                }, function (err) {
                    reject(err);
                })
            })(i)
        }
    })
}
Promise.allSettled = function (promises) {
    var resultArr = [];
    var count = 0;
    return new Promise(function (resolve, reject) {
        if (promises.__proto__.constructor !== Array) {
            var err = new TypeError('object is not iterable (cannot read property Symbol(Symbol.iterator))');
            reject(err);
            throw err;
        }
        for (var i = 0; i < promises.length; i++) {
            (function (i) {
                promises[i].then(function (res) {
                    count++;
                    resultArr[i] = {
                        status: "fulfilled",
                        value: res,
                    };
                    if (count === promises.length) {
                        resolve(resultArr);
                    }
                }, function (err) {
                    count++;
                    resultArr[i] = {
                        status: "rejected",
                        value: err,
                    };
                    if (count === promises.length) {
                        resolve(resultArr);
                    }
                })
            })(i)
        }
    })
}

Promise.any = function (promises) {
    var hasResolve = false;
    return new Promise(function (resolve, reject) {
        if (promises.__proto__.constructor !== Array) {
            var err = new TypeError('object is not iterable (cannot read property Symbol(Symbol.iterator))');
            reject(err);
            throw err;
        }
        for (var i = 0; i < promises.length; i++) {
            promises[i].then(function (res) {
                resolve(res);
            })
        }
        Promise.allSettled(promises).then(function (res) {
            if (!hasResolve) {
                reject('AggregateError: All promises were rejected');
            }
        })
    })
}
function dealThen(promise, x, resolve, reject) {
    if (x === promise) {
        var err = new TypeError('Chaining cycle detected for promise #<Promise>');
        console.error(err);
    }
    if (x) {
        if (x.__proto__.constructor === Promise) {
            x.then(resolve, reject);
        } else {
            resolve(x);
        }
    }
}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容