web前端面试题:您能读懂的Promise源码实现(手写代码)

时间:2022-07-23
本文章向大家介绍web前端面试题:您能读懂的Promise源码实现(手写代码),主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

Promise 是 web 前端工程师在面试的过程中很难绕过的一个坎。如果您目前处于对 Promise 一知半解,或仅仅是停留在可以使用的层面上,建议您跟着本文敲打练习一遍,相信您一定会有所收获!另外文章有点长……

一、实现Promise以下功能

const p1 = new Promise((resolve, reject) => {
    resolve("成功");
})
p1.then(value => {
    // 成功
    console.log(value);
})

const p2 = new Promise((resolve, reject) => {
    reject("失败");
})
p2.then(undefined, reason => {
    // 失败
    console.log(reason);
})

const p3 = new Promise((resolve, reject) => {
    throw "异常"
})
p3.then(undefined, reason => {
    // 异常
    console.log(reason);
})

1、根据上面的代码,我们不难推断出其基本结构:

/*
* 创建一个构造函数 Promise
* 该函数接收一个 executor 执行函数
* */
function Promise(executor) {
}

/*
* 为 Promise 函数增加 then 方法;
* then 方法接收两个类型为 function 的参数;
* 第一个参数onResolved为成功时调用的函数;
* 第二个参数onRejected为失败时调用的函数;
* */
Promise.prototype.then = function (onResolved,onRejected) {
}

2、Promise 对象存在三种状态:Pending(进行中)resolved(已成功)rejected(已失败)。我们可以将其设置为三个常量:

// 进行中状态
const _PENDING="pending";
// 已成功状态
const _RESOLVED="resolved";
// 已失败状态
const _REJECTED="rejected";

3、我们在实例化Promise时,resolvereject函数将会得到执行,一旦执行其实例的状态会由pending更改为resolvedrejected,然后在原型对象方法then当中进行接收。所以我们要干以下几个事情:

•实例中创建两个属性statusvalue•创建内部函数_resolve_reject用于更新statusvalue•立即执行executor函数

代码如下:

function Promise(executor){
    /****** 1、实例中创建两个属性`status`与`value` ******/
    // 设置状态初始值为 pending
    this.status = _PENDING;
    // 设置初始值为 undefined
    this.value = undefined;
   /****** 2、创建内部函数`_resolve`与`_reject`用于更新`status`与`value` ******/
    // 成功时执行
    function _resolve(value) {
        // 修改 promise 对象的状态为 resolve
        this.status = _RESOLVED;
        // 保存成功的数据
        this.value = value;
    }
    // 失败时执行
    function _reject(reason) {
        // 修改 promise 对象的状态为 resolve
        this.status = _REJECTED;
        // 保存失败的数据
        this.value = reason;
    }
    /****** 3、立即执行`executor`函数 ******/
    try{
        // 立即执行 executor
        executor(_resolve.bind(this),_reject.bind(this))
    }catch (err) {
        _reject.call(this,err);
    }
}

4、我们需要在then函数内,根据实例的状态state来判断要执行onResolved成功函数,还是onRejected失败函数。Promise的核心then函数初始代码如下:

Promise.prototype.then = function (onResolved,onRejected) {
    switch (this.status) {
        // 当状态为resolve时,执行onResolved,并传递结果
        case _RESOLVED:
            onResolved(this.value);
            break
        // 当状态为reject时,执行onRejected,并传递结果
        case _REJECTED:
            onRejected(this.value);
            break
    }
}

5、当前已完成代码如下:

// 进行中状态
const _PENDING="pending";
// 已成功状态
const _RESOLVED="resolved";
// 已失败状态
const _REJECTED="rejected";
/*
* 创建一个构造函数 Promise
* 该函数接收一个 executor 执行函数
* */
function Promise(executor){
    // 设置状态初始值为 pending
    this.status = _PENDING;
    // 设置初始值为 undefined
    this.value = undefined;
    // 成功时执行
    function _resolve(value) {
        // 修改 promise 对象的状态为 resolve
        this.status = _RESOLVED;
        // 保存成功的数据
        this.value = value;
    }
    // 失败时执行
    function _reject(reason) {
        // 修改 promise 对象的状态为 resolve
        this.status = _REJECTED;
        // 保存失败的数据
        this.value = reason;
    }
    try{
        // 立即执行 executor
        executor(_resolve.bind(this),_reject.bind(this))
    }catch (err) {
        _reject.call(this,err);
    }
}
/*
* 为 Promise 函数增加 then 方法;
* then 方法接收两个类型为 function 的参数;
* 第一个参数onResolved为成功时调用的函数;
* 第二个参数onRejected为失败时调用的函数;
* */
Promise.prototype.then = function (onResolved,onRejected) {
    switch (this.status) {
        // 当状态为resolve时,执行onResolved,并传递结果
        case _RESOLVED:
            onResolved(this.value);
            break
        // 当状态为reject时,执行onRejected,并传递结果
        case _REJECTED:
            onRejected(this.value);
            break
    }
}

二、Promise 的状态 state 只允许更改一次

Promise即承诺,一旦承诺便会给予结果,且结果是不允许更改的。也就是说状态state一旦确定便不可更改。

const p1 = new Promise((resolve, reject) => {
    resolve("成功");
    reject("失败");
})
p1.then(value => {
    // 不会执行
    console.log(value);
},reason=>{
    // 输出:失败
    console.log(reason);
})

以上代码正确的输出应该是成功,而我们自己封装的Promise输出结果却为失败

说明我们的statereject("失败")进行了二次更改,原因很简单:我们没有对当前的状态进行判断。

所以我们要对_resolve_reject进行调整,分别在其函数体内增加对当前状态的判断,如果不是初始状态pending则不会继续更新状态及数据。

在构造函数Promise中找到_resolve_reject函数,代码调整如下:

// 成功时执行
function _resolve(value) {
    // 如果为pending退出函数
    if (this.status !== "pending")
        return;
    // 修改 promise 对象的状态为 resolve
    this.status = _RESOLVED;
    // 保存成功的数据
    this.value = value;
}
// 失败时执行
function _reject(reason) {
    // 如果为pending退出函数
    if (this.status !== "pending")
        return;
    // 修改 promise 对象的状态为 resolve
    this.status = _REJECTED;
    // 保存失败的数据
    this.value = reason;
}

接下来,再来执行最初的程序,输出为成功,说明状态只允许被更新一次了!

三、then 函数是异步的

因为 then 函数是异步的,所以在正常情况下,以下代码的输出应该为:1 2 3。但是采用我们自己封装的Promise,其结果却为1 3 2。

原因:我们并未对then函数进行异步的处理。

const p = new Promise((resolve, reject) => {
    console.log(1);
    resolve("成功");
})
p.then(value=>{
    console.log(3);
    console.log()
})
console.log(2);

接下来,进入到then函数中。我们只需要将执行回调的代码用setTimeout进行包裹即可:

Promise.prototype.then = function (onResolved, onRejected) {
    switch (this.status) {
        // 当状态为resolve时,执行onResolved,并传递结果
        case _RESOLVED:
            // 通过 setTimeout 让代码异步执行
            setTimeout(() => {
                onResolved(this.value);
            })
            break
        // 当状态为reject时,执行onRejected,并传递结果
        case _REJECTED:
            // 通过 setTimeout 让代码异步执行
            setTimeout(() => {
                onRejected(this.value);
            })
            break
    }
}

再来执行,结果为1 2 3。问题顺利解决!

四、完成 Promise 的连缀调用(核心)

const p = new Promise((resolve, reject) => {
    resolve("成功");
})
const result = p.then();
// 输出status为 resolved 的 Promise 实例
console.log(result);
const p2 = new Promise((resolve, reject) => {
    resolve("失败");
})
const result2 = p2.then();
// 输出status为 resolved 的 Promise 实例
console.log(result2);
const p3 = new Promise((resolve, reject) => {
    throw "异常"
})
const result3 = p3.then();
// 输出status为 rejected 的 Promise 实例
console.log(result3);

1、正常情况下,上方代码不管成功与失败,then 函数的返回结果始终应该是一个Promise实例,且其状态均为resolved。如果出现异常报错,则返回的状态为rejected,如下:

但是,我们目前的then函数是没有返回值的,所以我们只能得到一个undefined,并且由于我们未给予 then 函数相对应的参数(类型为函数),还给我们飘红报错了:Uncaught TypeError: onResolved is not a function

所以接下来,我们要做三件事:

1、验证参数是否为函数。

2、让then函数直接返回Promise

3、更改promise的状态:异常执行reject,其它均执行resolve

•验证参数是否为函数:

// 防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数
onResolved = typeof onResolved === "function" ? onResolved : value => value;
onRejected = typeof onRejected === "function" ? onRejected : error => { throw error };

•让then函数返回promisethen函数完整代码如下:

Promise.prototype.then = function (onResolved, onRejected) {
    return new Promise((resolve, reject) => {
        // 防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数
        onResolved = typeof onResolved === "function" ? onResolved : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : error => {
            throw error
        };
        switch (this.status) {
            // 当状态为resolve时,执行onResolved,并传递结果
            case _RESOLVED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    onResolved(this.value);
                });
                break
            // 当状态为reject时,执行onRejected,并传递结果
            case _REJECTED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    onRejected(this.value);
                });
                break
        }
    })
}

•更改Promise的状态:异常执行reject,其它均执行resolve,并传值。

Promise.prototype.then = function (onResolved, onRejected) {
    return new Promise((resolve, reject) => {
        // 防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数
        onResolved = typeof onResolved === "function" ? onResolved : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : error => {
            throw error
        };
        switch (this.status) {
            // 当状态为resolve时,执行onResolved,并传递结果
            case _RESOLVED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    // 增加try方法,如果出现异常,执行reject
                    try {
                        onResolved(this.value);
                        // 无异常执行resolve
                        resolve(this.value);
                    } catch (err) {
                        // 出现异常,执行reject
                        reject(err);
                    }
                });
                break
            // 当状态为reject时,执行onRejected,并传递结果
            case _REJECTED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    // 增加try方法,如果出现异常,执行reject
                    try {
                        onRejected(this.value);
                        // 无异常执行resolve
                        resolve(this.value);
                    } catch (err) {
                        // 出现异常,执行reject
                        reject(err);
                    }
                });
                break
        }
    })
}

接下来,通过咱们封装的程序,可以得到准确的数据了:

2、我们知道then在其回调函数中返回非Promise的数据,最终得到的result是一个为resolved状态的Promise(成功的状态),倘若返回的是一个Promise数据,那么最终得到的便是该Promise的状态(成功或失败的状态),例如:

const p = new Promise((resolve, reject) => {
    resolve("成功");
})
const result = p.then(value=>{
    return "返回字符串"+value;
});
console.log("result",result);
const result2 = p.then(value=>{
    return new Promise((resolve,reject)=>{
        resolve("成功的Promise")
    })
});
console.log("result2",result2);
const result3 = p.then(value=>{
    return new Promise((resolve,reject)=>{
        reject("失败的Promise")
    })
});
console.log("result3",result3);

应该是这样的结果:

但是,通过我们自己封装的Promise得到的结果都是一样的:

•原因:没有在then函数中判断onResolvedonRejected返回类型。

•解决:判断onResolvedonRejected的返回结果是否为 Promise,如果是Promise,则将其状态与then要返回的Promise状态设为一致。

Promise.prototype.then = function (onResolved, onRejected) {
    return new Promise((resolve, reject) => {
        // 防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数
        onResolved = typeof onResolved === "function" ? onResolved : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : error => {
            throw error
        };
        switch (this.status) {
            // 当状态为resolve时,执行onResolved,并传递结果
            case _RESOLVED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    // 增加try方法,如果出现异常,执行reject
                    try {
                        let result = onResolved(this.value);
                        // 判断返回结果是否为Promise类型
                        if(result instanceof Promise){
                            // result.then(v => {
                            //     // 成功,修改返回的 Promise 状态为成功
                            //     resolve(v);
                            // }, r => {
                            //     // 失败,修改返回的 Promise 状态为失败
                            //     reject(r);
                            // });
                            // result 是 promise,下面这行代码是上方代码的简写形式
                            result.then(resolve,reject);
                        }else{
                            // 非Promise类型,将结果直接传递过去
                            resolve(result);
                        }
                    } catch (err) {
                        // 出现异常,执行reject
                        reject(err);
                    }
                });
                break
            // 当状态为reject时,执行onRejected,并传递结果
            case _REJECTED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    // 增加try方法,如果出现异常,执行reject
                    try {
                        let result = onRejected(this.value);
                        // 判断返回结果是否为Promise类型
                        if(result instanceof Promise){
                            // result.then(v => {
                            //     // 成功,修改返回的 Promise 状态为成功
                            //     resolve(v);
                            // }, r => {
                            //     // 失败,修改返回的 Promise 状态为失败
                            //     reject(r);
                            // });
                            // result 是 promise,下面这行代码是上方代码的简写形式
                            result.then(resolve,reject);
                        }else{
                            // 非Promise类型,将结果直接传递过去
                            resolve(result);
                        }
                    } catch (err) {
                        // 出现异常,执行reject
                        reject(err);
                    }
                });
                break
        }
    })
}

结果:

效果虽然出来了,但是这样的代码确实有些臃肿。

所以要对其进行优化:不难发现两个case内的代码除了回调函数不同,其它都是一样的,所以我们可以将其进行封装,并将回调函数作为参数传递。

封装优化后:

Promise.prototype.then = function (onResolved, onRejected) {
    return new Promise((resolve, reject) => {
        /*
        * 参数 cb 的值为 onResolved 或 onRejected 函数
        *  */
        function _callback(cb) {
            // 增加try方法,如果出现异常,执行reject
            try {
                let result = cb(this.value);
                // 判断返回结果是否为Promise类型
                if (result instanceof Promise) {
                    // result 是 promise,下面这行代码是上方代码的简写形式
                    result.then(resolve, reject);
                } else {
                    // 非Promise类型,将结果直接传递过去
                    resolve(result);
                }
            } catch (err) {
                // 出现异常,执行reject
                reject(err);
            }
        }
        // 防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数
        onResolved = typeof onResolved === "function" ? onResolved : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : error => {
            throw error
        };
        switch (this.status) {
            // 当状态为resolve时,执行onResolved,并传递结果
            case _RESOLVED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    _callback.call(this, onResolved);
                });
                break;
            // 当状态为reject时,执行onRejected,并传递结果
            case _REJECTED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    _callback.call(this, onRejected);
                });
                break;
        }
    })
}

3、程序写到这一步其实还隐藏着一个 bug,如果我们采用连缀的形式会有问题,代码如下:

let p1 = new Promise((resolve, reject) => {
    resolve('成功')
}).then(value => {
    console.log("我会输出")
}).then(value => {
    console.log("我不会输出")
})

正常来讲,两个then均会输出才对。而通过我们封装的Promise,只会将第一个输出。

•分析:因为我们现在的 Promise 是同步任务,所以当我们执行到第一个then的时候,当前Promise的状态已经确定为 resolved。而当执行到第二个then的时候,此时的Promise是通过第一个then得到的,又因为在第一个then当中有setTimeout,使其变为了异步,所以会造成resolvereject不会立即调用,最终导致在执行第二个 then 时,当前Promisestatuspending。也就是说我们更改状态后,回调方法没有得到执行。如果此时我们将封装then函数当中的setTimeout移除掉,则会恢复正常,但将其移除掉封装也就失去了意义。

•解决:我们已经知道原因是当Promise的状态发生变化时,then函数的回调没有得到调用。所以我们需要在改变状态后调用即可。可状态更改完成之后我们又如何才可以执行回调?在这个时候我们可以在实例当中创建一个属性onCallBacks用于存放回调函数队列,然后在执行then函数时判断当前状态如果为pending则说明为异步任务,只需将回调函数放置到onCallBacks 属性中。这样当异步修改完状态后,我们就可以通过onCallBacks执行回调了。代码:

•在实例当中创建一个属性onCallBacks用于存放回调函数队列。

// 添加回调函数队列
this.onCallBacks = [];

•在then 函数中判断当前状态为 pending 时,将回调函数放置到 onCallBacks 数组中。

// 当状态为 pending 时,将要执行的回调函数放置到队列中,待状态更改完毕后再调用。
case _PENDING:
    this.onCallBacks.push({
        onResolved() {
            //获取回调函数的执行结果
            _callback.call(this,onResolved);
        },
        onRejected() {
            _callback.call(this,onRejected);
        }
    });
    break;

•当异步修改完状态后,我们就可以通过 onCallBacks 执行回调了。

// 成功时执行
function _resolve(value) {
    if (this.status !== "pending")
        return;
    // 修改 promise 对象的状态为 resolve
    this.status = _RESOLVED;
    // 保存成功的数据
    this.value = value;
    //检查回调数组中是否存在数据
    if (this.onCallBacks.length > 0) {
        // 异步执行
        setTimeout(() => {
            this.onCallBacks.forEach(onCb => {
                onCb.onResolved.call(this);
            });
        });
    }
}
// 失败时执行
function _reject(reason) {
    if (this.status !== "pending")
        return;
    // 修改 promise 对象的状态为 resolve
    this.status = _REJECTED;
    // 保存失败的数据
    this.value = reason;
    //检查回调数组中是否存在数据
    if (this.onCallBacks.length > 0) {
        // 异步执行
        setTimeout(() => {
            this.onCallBacks.forEach(onCb => {
                onCb.onRejected.call(this);
            });
        });
    }
}

Promise 完整代码如下:

// 进行中状态
const _PENDING = "pending";
// 已成功状态
const _RESOLVED = "resolved";
// 已失败状态
const _REJECTED = "rejected";
/*
* 创建一个构造函数 Promise
* 该函数接收一个 executor 执行函数
* */
function Promise(executor) {
    // 设置状态初始值为 pending
    this.status = _PENDING;
    // 设置初始值为 undefined
    this.value = undefined;
    // 添加回调函数队列
    this.onCallBacks = [];
    // 成功时执行
    function _resolve(value) {
        if (this.status !== "pending")
            return;
        // 修改 promise 对象的状态为 resolve
        this.status = _RESOLVED;
        // 保存成功的数据
        this.value = value;
        //检查回调数组中是否存在数据
        if (this.onCallBacks.length > 0) {
            // 异步执行
            setTimeout(() => {
                this.onCallBacks.forEach(onCb => {
                    onCb.onResolved.call(this);
                });
            });
        }
    }
    // 失败时执行
    function _reject(reason) {
        if (this.status !== "pending")
            return;
        // 修改 promise 对象的状态为 resolve
        this.status = _REJECTED;
        // 保存失败的数据
        this.value = reason;
        //检查回调数组中是否存在数据
        if (this.onCallBacks.length > 0) {
            // 异步执行
            setTimeout(() => {
                this.onCallBacks.forEach(onCb => {
                    onCb.onRejected.call(this);
                });
            });
        }
    }
    try {
        // 立即执行 executor
        executor(_resolve.bind(this), _reject.bind(this))
    } catch (err) {
        _reject.call(this, err);
    }
}
/*
* 为 Promise 函数增加 then 方法;
* then 方法接收两个类型为 function 的参数;
* 第一个参数 onResolved 为成功时调用的函数;
* 第二个参数 onRejected 为失败时调用的函数;
* */
Promise.prototype.then = function (onResolved, onRejected) {
    return new Promise((resolve, reject) => {
        /*
        * 参数 cb 的值为 onResolved 或 onRejected 函数
        *  */
        function _callback(cb) {
            // 增加try方法,如果出现异常,执行reject
            try {
                let result = cb(this.value);
                // 判断返回结果是否为Promise类型
                if (result instanceof Promise) {
                    // result 是 promise,下面这行代码是上方代码的简写形式
                    result.then(resolve, reject);
                } else {
                    // 非Promise类型,将结果直接传递过去
                    resolve(result);
                }
            } catch (err) {
                // 出现异常,执行reject
                reject(err);
            }
        }
        // 防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数
        onResolved = typeof onResolved === "function" ? onResolved : value => value;
        onRejected = typeof onRejected === "function" ? onRejected : error => {
            throw error
        };
        switch (this.status) {
            // 当状态为resolve时,执行onResolved,并传递结果
            case _RESOLVED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    _callback.call(this, onResolved);
                });
                break;
            // 当状态为reject时,执行onRejected,并传递结果
            case _REJECTED:
                // 通过 setTimeout 让代码异步执行
                setTimeout(() => {
                    _callback.call(this, onRejected);
                });
                break;
            // 当状态为 pending 时,将要执行的回调函数放置到队列中,待状态更改完毕后再调用。
            case _PENDING:
                this.onCallBacks.push({
                    onResolved() {
                        //获取回调函数的执行结果
                        _callback.call(this,onResolved);
                    },
                    onRejected() {
                        _callback.call(this,onRejected);
                    }
                });
                break;
        }
    })
}

截止到目前,我们已经完成了Promise的链式调用。

五、其它 API

// catch方法的封装
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}
// 函数对象 resolve 的封装
Promise.resolve = function (value) {
    return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
            value.then(resolve, reject);
        } else {
            resolve(value);
        }
    });
}
// 函数对象 reject 的封装
Promise.reject = function (reason) {
    return new Promise((resolve, reject) => {
        reject(reason);
    })
}
//函数对象 all 的封装
Promise.all = function (promises) {
    return new Promise((resolve, reject) => {
        let pValues = [];
        let flag = 0;
        for (let i = 0; i < promises.length; i++) {
            promises[i].then(v => {
                pValues[i] = v;
                flag++;
                if (flag >= promises.length) {
                    resolve(pValues);
                }
            }, r => {
                reject(r);
            })
        }
    });
}
// 函数对象 race
Promise.race = function (promises) {
    return new Promise((resolve, reject) => {
        for(let i=0;i<promises.length;i++){
            promises[i].then(value=>{
                resolve(value);
            }, reason=>{
                reject(reason);
            })
        }
    });
}

六、class 封装完整版

(function(window){
    // 进行中状态
    const _PENDING = "pending";
    // 已成功状态
    const _RESOLVED = "resolved";
    // 已失败状态
    const _REJECTED = "rejected";
    class MyPromise {
        constructor(executor) {
            // 设置状态初始值为 pending
            this.status = _PENDING;
            // 设置初始值为 undefined
            this.value = undefined;
            // 添加回调函数队列
            this.onCallBacks = [];
            // 成功时执行
            function _resolve(value) {
                if (this.status !== "pending")
                    return;
                // 修改 MyPromise 对象的状态为 resolve
                this.status = _RESOLVED;
                // 保存成功的数据
                this.value = value;
                //检查回调数组中是否存在数据
                if (this.onCallBacks.length > 0) {
                    // 异步执行
                    setTimeout(() => {
                        this.onCallBacks.forEach(onCb => {
                            onCb.onResolved.call(this);
                        });
                    });
                }
            }
            // 失败时执行
            function _reject(reason) {
                if (this.status !== "pending")
                    return;
                // 修改 MyPromise 对象的状态为 resolve
                this.status = _REJECTED;
                // 保存失败的数据
                this.value = reason;
                //检查回调数组中是否存在数据
                if (this.onCallBacks.length > 0) {
                    // 异步执行
                    setTimeout(() => {
                        this.onCallBacks.forEach(onCb => {
                            onCb.onRejected.call(this);
                        });
                    });
                }
            }
            try {
                // 立即执行 executor
                executor(_resolve.bind(this), _reject.bind(this))
            } catch (err) {
                _reject.call(this, err);
            }
        }
        then(onResolved, onRejected) {
            return new MyPromise((resolve, reject) => {
                /*
                * 参数 cb 的值为 onResolved 或 onRejected 函数
                *  */
                function _callback(cb) {
                    // 增加try方法,如果出现异常,执行reject
                    try {
                        let result = cb(this.value);
                        // 判断返回结果是否为MyPromise类型
                        if (result instanceof MyPromise) {
                            // result 是 MyPromise,下面这行代码是上方代码的简写形式
                            result.then(resolve, reject);
                        } else {
                            // 非MyPromise类型,将结果直接传递过去
                            resolve(result);
                        }
                    } catch (err) {
                        // 出现异常,执行reject
                        reject(err);
                    }
                }
                // 防止使用者不传成功或失败回调函数,所以成功失败回调都给了默认回调函数
                onResolved = typeof onResolved === "function" ? onResolved : value => value;
                onRejected = typeof onRejected === "function" ? onRejected : error => {
                    throw error
                };
                switch (this.status) {
                    // 当状态为resolve时,执行onResolved,并传递结果
                    case _RESOLVED:
                        // 通过 setTimeout 让代码异步执行
                        setTimeout(() => {
                            _callback.call(this, onResolved);
                        });
                        break;
                    // 当状态为reject时,执行onRejected,并传递结果
                    case _REJECTED:
                        // 通过 setTimeout 让代码异步执行
                        setTimeout(() => {
                            _callback.call(this, onRejected);
                        });
                        break;
                    // 当状态为 pending 时,将要执行的回调函数放置到队列中,待状态更改完毕后再调用。
                    case _PENDING:
                        this.onCallBacks.push({
                            onResolved() {
                                //获取回调函数的执行结果
                                _callback.call(this, onResolved);
                            },
                            onRejected() {
                                _callback.call(this, onRejected);
                            }
                        });
                        break;
                }
            })
        }
        catch = function (onRejected) {
            return this.then(undefined, onRejected);
        }
        // 函数对象 resolve 的封装
        static resolve(value) {
            return new MyPromise((resolve, reject) => {
                if (value instanceof MyPromise) {
                    value.then(resolve, reject);
                } else {
                    resolve(value);
                }
            });
        }
        // 函数对象 reject 的封装
        static reject(reason) {
            return new MyPromise((resolve, reject) => {
                reject(reason);
            })
        }
        //函数对象 all 的封装
        static all(MyPromises) {
            return new MyPromise((resolve, reject) => {
                let pValues = [];
                let flag = 0;
                for (let i = 0; i < MyPromises.length; i++) {
                    MyPromises[i].then(v => {
                        pValues[i] = v;
                        flag++;
                        if (flag >= MyPromises.length) {
                            resolve(pValues);
                        }
                    }, r => {
                        reject(r);
                    })
                }
            });
        }
        //函数对象 race
        static race(MyPromises) {
            return new MyPromise((resolve, reject) => {
                for (let i = 0; i < MyPromises.length; i++) {
                    MyPromises[i].then(value => {
                        resolve(value);
                    }, reason => {
                        reject(reason);
                    })
                }
            });
        }
    }
    window.MyPromise = MyPromise;
})(window)