Realize promise step by step from zero handwriting

Time:2020-3-25

I read the article shared by Peter Tan Jinjie yesterday, and realized the promise a + standard step by step from scratch. Thank you for sharing. I tried to realize a beggar version

Core idea 1:
The implementation of the then method, and the parameters of the then method are pushed as callback functions
The implementation of catch method, and the parameters of catch are pushed as callback functions

Core idea 2:
The implementation of chain call only needs to return this, jQuery and zepto source code

The complete code is as follows:

class HackPromise {
    constructor(fn) {
        this.status = this.PROMISE_STATUS.PENDING;
        this.onFulfilledStack = [];
        this.onRejectedStack = [];
        fn(this.onResolve, this.onReject);
    }

    PROMISE_STATUS = Object.freeze(
        {
            PENDING: 'pending',
            FULFILLED: 'fulfilled',
            REJECTED: 'rejected'
        }
    );

    static resolve = value => new HackPromise(resolve => resolve(value));
    static reject = error => new HackPromise((resolve, reject) => reject(error));
    static all = promiseArr => {
        const promiseArrLength = promiseArr.length;
        const promiseResArr = [];
        let promiseResArrEnd = false;

        return new HackPromise((resolve, reject) => {
            for (let i = 0; i < promiseArrLength; i++) {
                promiseArr[i]
                    .then(res => {
                        if (promiseResArrEnd) {
                            return;
                        }

                        promiseResArr[i] = res;

                        if (promiseResArr.filter(promiseRes => promiseRes).length === promiseArrLength) {
                            promiseResArrEnd = true;
                            resolve(promiseResArr);
                        }
                    })
                    .catch(e => {
                        if (promiseResArrEnd) {
                            return;
                        }

                        promiseResArrEnd = true;
                        reject(e);
                    });
            }
        });
    };
    static race = promiseArr => {
        let promiseResArrEnd = false;

        return new HackPromise((resolve, reject) => {
            for (let i = 0; i < promiseArr.length; i++) {
                promiseArr[i]
                    .then(res => {
                        if (promiseResArrEnd) {
                            return;
                        }

                        promiseResArrEnd = true;
                        resolve(res);
                    })
                    .catch(e => {
                        if (promiseResArrEnd) {
                            return;
                        }

                        promiseResArrEnd = true;
                        reject(e);
                    });
            }
        });
    };

    onResolve = value => {
        if (this.status === this.PROMISE_STATUS.PENDING) {
            setTimeout(() => {
                this.status = this.PROMISE_STATUS.FULFILLED;
                this.onFulfilledStack.forEach(cb => cb(value));
            }, 0);
        }

        return this;
    };

    onReject = error => {
        if (this.status === this.PROMISE_STATUS.PENDING) {
            setTimeout(() => {
                this.status = this.PROMISE_STATUS.REJECTED;
                this.onRejectedStack.forEach(cb => cb(error));
            }, 0);
        }

        return this;
    };

    then = onFulfilled => {
        if (this.status === this.PROMISE_STATUS.PENDING) {
            this.onFulfilledStack.push(onFulfilled);
        }

        return this;
    };

    catch = onRejected => {
        if (this.status === this.PROMISE_STATUS.PENDING) {
            this.onRejectedStack.push(onRejected);
        }

        return this;
    };
}