SOURCE

class PromiseM {
    static status = {
        pendding: 'pendding',
        resolved: 'resolved',
        rejected: 'rejected'
    }

    static resolvePromise(promise2, x, resolve, reject) {
        if (promise2 === x) {
            reject(new TypeError('循环引用'))
        }

        let called
        if (x !== null && (typeof x === 'object') || typeof x === 'function') {
            try {
                let then = x.then
                if (typeof then === 'function') {
                    then.call(x, (y) => {
                        // resolve(y)
                        if (called) return
                        called = true
                        PromiseM.resolvePromise(promise2, y, resolve, reject)
                    }, (e) => {
                        if (called) return
                        called = true
                        reject(e)
                    })
                } else {
                    if (called) return
                    called = true
                    resolve(x)
                }
            } catch (e) {
                if (called) return
                called = true
                reject(e)
            }
        } else {
            // 递归结束条件
            resolve(x)
        }
    }

    constructor(executor) {
        this.status = PromiseM.status.pendding
        this.value = undefined
        this.reson = undefined
        this.onFulfilledCallbacks = []
        this.onRejectedCallbacks = []

        let resolve = (value) => {
            // console.log(value instanceof PromiseM)
            if (value instanceof PromiseM) {
                return value.then(resolve, reject)
            }
            setTimeout(() => {
                if (this.status === PromiseM.status.pendding) {
                    this.status = PromiseM.status.resolved
                    this.value = value
                    this.onFulfilledCallbacks.forEach(cb => cb(this.value))
                }
            }, 0)
        }
        let reject = (reson) => {
            setTimeout(() => {
                if (this.status = PromiseM.status.pendding) {
                    this.status = PromiseM.status.rejected
                    this.reson = reson
                    this.onRejectedCallbacks.forEach(cb => cb(this.reson))

                }
            }, 0)
        }

        try {
            executor(resolve, reject)
        } catch (e) {
            reject(e)
        }
    }

    then(onFulfilled, onRejected) {
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : value => value
        onRejected = typeof onRejected === 'function' ? onRejected : err => { throw err }

        let promise2 = new PromiseM((resolve, reject) => {
            if (this.status === PromiseM.status.pendding) {
                this.onFulfilledCallbacks.push(() => {
                    try {
                        let x = onFulfilled(this.value)
                        PromiseM.resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                })
                this.onRejectedCallbacks.push(() => {
                    try {
                        let x = onRejected(this.reson)
                        PromiseM.resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                })

            }
            if (this.status === PromiseM.status.resolved) {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value)
                        PromiseM.resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0)
            }
            if (this.status === PromiseM.status.rejected) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reson)
                        PromiseM.resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0)
            }
        })

        return promise2
    }

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

var p = new PromiseM((resolve, reject) => {
    // setTimeout(() => {
    //     resolve(2)
    // }, 200)
    // resolve(new PromiseM(resolve => {
    //     resolve('promise result')
    // }))
    resolve('sync')
})

var p1 = p.then((res) => {
    console.log(`fulfilled:${res}`)
    return { res: res }
    // return new PromiseM(resolve => {
    //     resolve(new PromiseM(resolve => {
    //         resolve('p1>p res')
    //     }))
    // })
}).catch(e => {
    console.log(e)
}).then((res) => {
    console.log(`p2.fulfilled:${res}`)
})
console 命令行工具 X clear

                    
>
console