Promise 系列(5)-- Promise 方法的异常捕获以及 then 方法实现可选参数

170 阅读2分钟

写在开头:如果被大佬们看到了有错误还请斧正,如果把萌新带到了沟里,你在爬出来就好了(手动滑稽)

在 myPromise 实现的过程中是没有对于异常的处理,一个成熟的类或者方法都是有对错误和异常的处理的,所以接下来处理 myPromise 中的异常情况。

1、捕获 myPromise 中的错误

1、处理回调函数执行错误的情况
let promise = new myPromise(
    //  在此处就发生了错误
    (resolve, reject) => {
        throw new Error('出错了');
    }
);
promise.then((value) => {
    console.log(value);
}, (reason) => {
    console.log(reason);  //  这里会抛出错误
});

*
*
constructor(executor) {
    try {
        executor(this.resolve, this.reject);
    } catch (error) {
        this.reject(error);
    }
}
*
*

2、处理 then 方法中回调函数发成错误的情况

let promise = new myPromise((resolve, reject) => {
        resolver('成功');
    }
);
promise.then((value) => {
    console.log(value);
    throw new Error('出错了');
}).then(() => {
    //  在这里会得到上一个 then 方法抛出的错误
});


*
*
if (this.status === FULFILLED) {
    setTimeout(() => {
        try {
            let x = successCallback(this.value);
            argParsing(thenPromise, x, resolve, reject);
        } catch (error) {
            //  Q: 为啥要用 reject
            //  A: 链式调用 then 方法的时候,上一个发生了错误的 then 需要在下一个 then 方法中抛出
            reject(error);
        }
    }, 0);
} else if (this.status === REJECTED) {
    setTimeout(() => {
        try {
            let x = failCallback(this.reason);
            argParsing(thenPromise, x, resolve, reject);
        } catch (error) {
            reject(error);
        }
    }, 0);
} else {
    this.successCallback.push(() => {
        setTimeout(() => {
            try {
                let x = successCallback(this.value);
                argParsing(thenPromise, x, resolve, reject);
            } catch (error) {
                reject(error);
            }
        }, 0);
    });
    this.failCallback.push(() => {
        setTimeout(() => {
            try {
                let x = failCallback(this.reason);
                argParsing(thenPromise, x, resolve, reject);
            } catch (error) {
                reject(error);
            }
        }, 0);
    });
}
*
*

这样就捕获到了 myPromise 在运行时的异常情况

2、then 方法的参数变为可选参数

在 Promise 中 then 方法中的成功回调失败回调是可选参数,属于可写可不写的

let promise = new Promise((resolve, reiect) => {
    resolve(100);
});

promise
    .then()
    .then()
    .then()
    .then((value) => {
    console.log(value);  //  100
});

当在前一个 then 方法中不传递任何参数的时候,实际上等同于传递了一个返回了自己的回调函数,大概就是酱婶儿的:

截屏2021-04-08 下午6.13.49.png

所以只要判断一下这个 then 方法有没有传递参数应该就可以了,如果没有传递参数,那么就给他补一个参数

*
*
then(successCallback, failCallback) {
    successCallback = successCallback ? successCallback : value => value;
    failCallback = failCallback ? failCallback : reason => { throw reason };
    let thenPromise = new myPromise((resolve, reject) => {
*
*

运行起来康康没啥问题

截屏2021-04-08 下午6.29.41.png

到此 Promise 的 then 方法就得到了基本的完善,目前为止代码如下:

const PENDING = 'pending';
const FULFILLED = 'fulfilled';
const REJECTED = 'rejected'

class myPromise {
    constructor(executor) {
        try {
            executor(this.resolve, this.reject);
        } catch (error) {
            this.reject(error);
        }
    }

    status = PENDING;
    value = undefined;
    reason = undefined;
    successCallback = [];
    failCallback = [];

    resolve = (value) => {
        if (this.status !== PENDING) return;
        this.status = FULFILLED;
        this.value = value;
        while (this.successCallback.length) {
            this.successCallback.shift()();
        }
    }

    reject = (reason) => {
        if (this.status !== PENDING) return;
        this.status = REJECTED;
        this.reason = reason;
        while (this.failCallback.length) {
            this.failCallback.shift()();
        }
    }

    then(successCallback, failCallback) {
        successCallback = successCallback ? successCallback : value => value;
        failCallback = failCallback ? failCallback : reason => { throw reason };
        let thenPromise = new myPromise((resolve, reject) => {
            if (this.status === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = successCallback(this.value);
                        argParsing(thenPromise, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                }, 0);
            } else if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = failCallback(this.reason);
                        argParsing(thenPromise, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                }, 0);
            } else {
                this.successCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = successCallback(this.value);
                            argParsing(thenPromise, x, resolve, reject);
                        } catch (error) {
                            reject(error);
                        }
                    }, 0);
                });
                this.failCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = failCallback(this.reason);
                            argParsing(thenPromise, x, resolve, reject);
                        } catch (error) {
                            reject(error);
                        }
                    }, 0);
                });
            }
        })
        return thenPromise;
    }
}

function argParsing(thenPromise, x, resolve, reject) {
    if (thenPromise === x) return reject(new TypeError('Promise 被循环调用了'));
    if (x instanceof myPromise) {
        x.then(resolve, reject);
    } else {
        resolve(x);
    }
}

Promise 的 then 方法到此就得到的完善,然而 Promise 除了 then 方法之外还有 all,Promise.resolve,finally,catch,接下来逐一简单进行实现。