SOURCE

const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class VPromise {
    constructor(excutor) {
        this.status = PENDING
        this.value = undefined
        this.fulfilledQueues = []
        this.rejectedQueues = []

        try {
            excutor(this._resolve, this._reject)
        } catch (e) {
            this._reject(e)
        }
    }

    _resolve = value => {
        const run = () => {
            if (this.status === PENDING) {
                if (value instanceof VPromise) {
                    value.then(res => {
                        this.status = FULFILLED
                        this.value = value
                        let cb
                        while (cb = this.fulfilledQueues.shift()) {
                            cb(res)
                        }
                    }, err => {
                        this.status = REJECTED
                        this.value = err
                        let cb
                        while (cb = this.rejectedQueues.shift()) {
                            cb(err)
                        }
                    })
                } else {
                    this.status = FULFILLED
                    this.value = value
                    let cb
                    while (cb = this.fulfilledQueues.shift()) {
                        cb(value)
                    }
                }
            }
        }
        setTimeout(() => run(), 0)
    }

    _reject = reason => {
        const run = () => {
            if (this.status === PENDING) {
                this.status = REJECTED
                this.value = reason
                let cb
                while (cb = this.rejectedQueues.shift()) {
                    cb(reason)
                }
            }
        }
        setTimeout(() => run(), 0)
    }

    then(onFulfilled, onRejected) {
        const { status, value, fulfilledQueues, rejectedQueues } = this
        return new VPromise((_resolveNext, _rejectNext) => {
            let resolve = val => {
                try {
                    if (typeof onFulfilled !== 'function') {
                        _resolveNext(val)
                    } else {
                        let x = onFulfilled(val)
                        if (x instanceof VPromise) {
                            // 执行x,成功则调用
                            x.then(_resolveNext, _rejectNext)
                        } else {
                            _resolveNext(x)
                        }
                    }
                } catch (e) {
                    _rejectNext(e)
                }
            }

            let reject = val => {
                try {
                    if (typeof onRejected !== 'function') {
                        _rejectNext(val)
                    } else {
                        let x = onRejected(val)
                        if (x instanceof VPromise) {
                            // 执行x,成功则调用
                            x.then(_resolveNext, _rejectNext)
                        } else {
                            _resolveNext(x)
                        }
                    }
                } catch (e) {
                    _rejectNext(e)
                }
            }

            if (status === FULFILLED) {
                resolve(value)
            }
            if (status === REJECTED) {
                reject(value)
            }
            // 执行器是异步的情况,把回调放到回调队列里
            if (status === PENDING) {
                fulfilledQueues.push(resolve)
                rejectedQueues.push(reject)
            }
        })
    }

    catch(onRejected) {
        return this.then(undefined, onRejected)
    }

    static resolve(value) {
        if (value instanceof VPromise) return value
        return new VPromise(resolve => resolve(value))
    }

    static reject(value) {
        return new VPromise((resolve, reject) => reject(value))
    }

    static all(list) {
        return new VPromise((resolve, reject) => {
            let values = []
            let count = 0

            for (let [i, value] of list.entries()) {
                this.resolve(value).then(res => {
                    values.push(res)
                    count += 1

                    if (count === list.length) resolve(values)
                }, err => {
                    reject(err)
                })
            }
        })
    }

    static race(list) {
        return new VPromise((resolve, reject) => {
            for (let value of list) {
                this.resolve(value).then(res => {
                    resolve(res)
                }, err => {
                    reject(err)
                })
            }
        })
    }

}

const promise1 = VPromise.resolve(3);
const promise2 = 42;
const promise3 = new VPromise((resolve, reject) => {
    setTimeout(resolve, 100, 'foo');
});

VPromise.all([promise1, promise2, promise3]).then((values) => {
    console.log('success: ' + values);
}, err => {
    console.log('error: ' + err)
});

VPromise.race([promise1, promise2, promise3]).then((values) => {
    console.log('race success: ' + values);
}, err => {
    console.log('race error: ' + err)
});



console 命令行工具 X clear

                    
>
console