乐趣区

关于promise:手写Promise-实例方法catchfinally

手写 Promise – 实现一个根底的 Promise
手写 Promise – 实例办法 catch、finally
手写 Promise – 罕用静态方法 all、any、resolve、reject、race

上一篇文章手写了一个根底的 Promise,咱们持续来欠缺它,为其增加常常用到的 catch 和 finally 办法

catch & finally

catch() 办法返回一个 Promise,并且解决回绝的状况。咱们晓得 then 办法的第二个参数其实就是干这个用的,catch 只是一个别名。

finally() 办法返回一个 Promise。在 promise 完结时,无论后果是 fulfilled 或者是 rejected,都会执行指定的回调函数。和 catch 一样,也只是对 then 的一个简写,相当于是传入的函数既是 onFulfilled 也是 onRejected。

有一点须要留神,finally 和 catch 办法只是 then 的一个别名,实际上返回的还是一个 promise,齐全能够这样写:promise.then().finally().then().catch().then()

咱们把上一章节的代码拷过去,而后向外面增加 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 也没啥问题。

退出移动版