ES5/ES6 实现基本 Promise



  
    
    
    
    ES5-Promise
  
  
    
  

ES6-Promise

const PENDING = 'pending';
const FULLFILLED = 'fullfilled';
const REJECTED = 'rejected';

function resolvePromise(promise2, x, resolve, reject) {
    if (x === promise2) {
        throw Error('不能返回自身');
    }
    if (x instanceof _Promise) {
        if (x.status === PENDING) {
            x.then(
                y => resolvePromise(promise2, y, resolve, reject),
                reject
            )
        } else if (x.status === FULLFILLED) {
            resolve(x.value);
        } else {
            reject(x.value);
        }
    } else if (x !== null && (typeof x === 'object' || typeof x === 'function')) {
        let then = null;
        try {
            then = x.then;
        } catch (error) {
            reject(error);
        }
        if (typeof then === 'function') {
            let called = false;
            try {
                then.call(
                    x,
                    res => {
                        if (called) {
                            return;
                        }
                        called = true;
                        resolvePromise(promise2, res, resolve, reject);
                    },
                    error => {
                        if (called) {
                            return;
                        }
                        called = true;
                        reject(error);
                    }
                )
            } catch (error) {
                if (called) {
                    return;
                }
                called = true;
                reject(error);
            }
        } else {
            resolve(x);
        }
    } else {
        resolve(x);
    }
}

class _Promise {
    constructor(executor) {
        this.status = PENDING;
        this.value = null;
        this.fullfilledCallbacks = [];
        this.rejectedCallbacks = [];

        try {
            executor(this.resolve.bind(this), this.reject.bind(this));
        } catch (error) {
            this.reject(error);
        }
    }
    resolve(value) {
        if (this.status === PENDING) {
            setTimeout(() => {
                this.status = FULLFILLED;
                this.value = value;
                this.fullfilledCallbacks.forEach(callback => callback(value));
            })
        }
    }

    reject(reason) {
        if (this.status === PENDING) {
            setTimeout(() => {
                this.status = REJECTED;
                this.value = reason;
                this.rejectedCallbacks.forEach(callback => callback(reason));
            })

        }
    }

    then(onFullfilled, onRejected) {
        onFullfilled = typeof onFullfilled === 'function' ? onFullfilled : value => value;
        onRejected = typeof onRejected === 'function' ? onRejected : error => { throw Error(error) }

        let promise2 = new _Promise((resolve, reject) => {
            if (this.status === PENDING) {
                this.fullfilledCallbacks.push(() => {
                    try {
                        let x = onFullfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
                this.rejectedCallbacks.push(() => {
                    try {
                        let x = onRejected(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            }

            if (this.status === FULLFILLED) {
                setTimeout(() => {
                    try {
                        let x = onFullfilled(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            }

            if (this.status === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.value);
                        resolvePromise(promise2, x, resolve, reject);
                    } catch (error) {
                        reject(error);
                    }
                });
            }
        });
        return promise2;
    }
}

你可能感兴趣的:(es6)