# 手写Class形式的Promise

  1. 三个状态,并且状态只能改变一次
  2. 异步回调的收集
  3. resolve、reject

/**
 * 可借鉴的文章:
 * 1. https://segmentfault.com/a/1190000016550260
 * 2. https://www.cnblogs.com/wjlbk/p/12633344.html
 */
class Promise {
    static PENDING = 'PENDING'; // 等待态
    static ONFULFILLED = 'ONFULFILLED'; // 成功态
    static ONREJECTED = 'ONREJECTED'; //失败态
    constructor(executor) {
        this.status = Promise.PENDING;
        this.value = void 0;
        this.reason = void 0;
        this.fulfilledCallbacks = []; // 收集成功的回调
        this.rejectedCallbacks = []; // 收集失败的回调
        let resolve = (value) => {
            if (this.status === Promise.PENDING) { // Promise的状态只能改变一次
                this.value = value;
                this.status = Promise.ONFULFILLED;
                this.fulfilledCallbacks.forEach(fn => fn())
            }
        }
        let reject = (reason) => {
            if (this.status === Promise.PENDING) {  // Promise的状态只能改变一次
                this.reason = reason;
                this.status = Promise.ONREJECTED;
                this.rejectedCallbacks.forEach(fn => fn());
            }
        }
        try {
            executor(resolve, reject);
        } catch (error) {
            reject(error);
        }
    }


    then(onFulfilled, onRejected) {
        return new Promise((resolve, reject) => {  // 链式调用的关键,返回一个新的promise
            if (this.status === Promise.ONFULFILLED) {
                try {
                    let x = onFulfilled(this.value);
                    Promise.resolvePromise(x, resolve, reject);
                } catch (error) {
                    reject(error);
                }
            }
            if (this.status === Promise.ONREJECTED) {
                try {
                    let x = onRejected(this.reason);
                    Promise.resolvePromise(x, resolve, reject);
                } catch (error) {
                    reject(error);
                }
            }
            // 异步的时候,状态还未更改, 需要收集回调
            if (this.status === Promise.PENDING) {
                this.fulfilledCallbacks.push(() => {
                    try {
                        let x = onFulfilled(this.value);
                        Promise.resolvePromise(x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
                this.rejectedCallbacks.push(() => {
                    try {
                        let x = onRejected(this.reason);
                        Promise.resolvePromise(x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            }
        })
    }
    /**
     * Promise.all()
     * 1. 接收一个可迭代的数据结构,且该数据结构的成员是promise对象。 
     * 2. all方法发挥一个promise实例
     * 3. 返回的实例的状态有两种情况
     *      3.1 第一种:成员都成功态,则成功回调是一个所有成员返回值组成的有顺序的数组
     *      3.2 第二种:只要有一个失败态,则第一个失败态的返回值,传递出来。
     */
    static all(promiseArr) {
        return new Promise((resolve, reject) => {
            let result = [];
            promiseArr.forEach((promiseItem, index) => {
                promiseItem.then(value => {
                    result[index] = value;
                    if (result.length === promiseArr.length) { // 决定什么时候resolve
                        resolve(result);
                    }
                }, error => {
                    reject(error);
                })
            })
        })
    }
    /**
     * 返回一个promise实例
     * 只要有一个状态改变了,就执行回调。
     */
    static race(promiseArr) {
        return new Promise((resolve, reject) => {
            promiseArr.forEach(promiseItem => {
                promiseItem.then(value => {
                    resolve(value);
                }, err => {
                    reject(err);
                })
            })
        })
    }

    static resolvePromise(x, resolve, reject) {
        if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
            try {
                let then = x.then;
                then.call(x, y => {
                    resolve(y);
                }, r => {
                    reject(r);
                })
            } catch (error) {
                reject(error);
            }
        } else {
            resolve(x);
        }
    }
}

module.exports = Promise;
作者:王龙楷; 标签:原创; 提交时间: 1/14/2021, 4:22:34 PM