手写Promise - 实例方法catch、finally

手写Promise - 实现一个基础的Promise
手写Promise - 实例方法catch、finally
手写Promise - 经常使用静态方法all、any、resolve、reject、racejavascript

上一篇文章手写了一个基础的Promise,咱们继续来完善它,为其添加常常用到的catch和finally方法java

catch & finally

catch() 方法返回一个Promise,而且处理拒绝的状况。咱们知道then方法的第二个参数其实就是干这个用的,catch只是一个别名。segmentfault

finally() 方法返回一个Promise。在promise结束时,不管结果是fulfilled或者是rejected,都会执行指定的回调函数。和catch同样,也只是对then的一个简写,至关因而传入的函数既是onFulfilled也是onRejected。数组

有一点须要注意,finally和catch方法只是then的一个别名,实际上返回的仍是一个promise,彻底能够这样写:promise.then().finally().then().catch().then()promise

咱们把上一章节的代码拷过来,而后向里面添加catch和finally方法。函数

class WPromise {
    static pending = 'pending';
    static fulfilled = 'fulfilled';
    static rejected = 'rejected';

    constructor(executor) {
        this.status = WPromise.pending; // 初始化状态为pending
        this.value = undefined; // 存储 this._resolve 即操做成功 返回的值
        this.reason = undefined; // 存储 this._reject 即操做失败 返回的值
        // 存储then中传入的参数
        // 至于为何是数组呢?由于同一个Promise的then方法能够调用屡次
        this.callbacks = [];
        executor(this._resolve.bind(this), this._reject.bind(this));
    }

    // onFulfilled 是成功时执行的函数
    // onRejected 是失败时执行的函数
    then(onFulfilled, onRejected) {
        // 返回一个新的Promise
        return new WPromise((nextResolve, nextReject) => {
            // 这里之因此把下一个Promsie的resolve函数和reject函数也存在callback中
            // 是为了将onFulfilled的执行结果经过nextResolve传入到下一个Promise做为它的value值
            this._handler({
                nextResolve,
                nextReject,
                onFulfilled,
                onRejected
            });
        });
    }

    // catch方法只有一个参数用于处理错误的状况
    catch(onRejected) {
        return this.then(null, onRejected);
    }

    finally(onFinally) {
        return this.then(onFinally, onFinally);
    }

    _resolve(value) {
        // 处理onFulfilled执行结果是一个Promise时的状况
        // 这里可能理解起来有点困难
        // 当value instanof WPromise时,说明当前Promise确定不会是第一个Promise
        // 而是后续then方法返回的Promise(第二个Promise)
        // 咱们要获取的是value中的value值(有点绕,value是个promise时,那么内部存有个value的变量)
        // 怎样将value的value值获取到呢,能够将传递一个函数做为value.then的onFulfilled参数
        // 那么在value的内部则会执行这个函数,咱们只须要将当前Promise的value值赋值为value的value便可
        if (value instanceof WPromise) {
            value.then(
                this._resolve.bind(this),
                this._reject.bind(this)
            );
            return;
        }

        this.value = value;
        this.status = WPromise.fulfilled; // 将状态设置为成功

        // 通知事件执行
        this.callbacks.forEach(cb => this._handler(cb));
    }

    _reject(reason) {
        if (reason instanceof WPromise) {
            reason.then(
                this._resolve.bind(this),
                this._reject.bind(this)
            );
            return;
        }

        this.reason = reason;
        this.status = WPromise.rejected; // 将状态设置为失败

        this.callbacks.forEach(cb => this._handler(cb));
    }

    _handler(callback) {
        const {
            onFulfilled,
            onRejected,
            nextResolve,
            nextReject
        } = callback;

        if (this.status === WPromise.pending) {
            this.callbacks.push(callback);
            return;
        }

        if (this.status === WPromise.fulfilled) {
            // 传入存储的值
            // 未传入onFulfilled时,将undefined传入
            const nextValue = onFulfilled
                ? onFulfilled(this.value)
                : undefined;
            nextResolve(nextValue);
            return;
        }

        if (this.status === WPromise.rejected) {
            // 传入存储的错误信息
            // 一样的处理
            const nextReason = onRejected
                ? onRejected(this.reason)
                : undefined;
            nextReject(nextReason);
        }
    }
}

是的,就是这么简单,如今来测试一下:测试

function fetchData() {
    return new WPromise((resolve, reject) => {
        setTimeout(() => {
            reject(1);
        }, 1000);
    });
}

fetchData().finally((data) => {
    return data + 10;
}).finally((data) => {
    return new WPromise((resolve, reject) => {
        reject(data + 10);
    });
}).finally((data) => {
    console.log(data); // 21
})

以上就是catch和finally的模拟实现,若是理解了then的工做原理的话,理解catch和finally也没啥问题。fetch

相关文章
相关标签/搜索