SOURCE

function _Promise (executor) {
    const self = this
    self.status = 'pending'
    self.data = undefined
    self.onResolvedCallBack = []
    self.onRejectedCallBack = []

    function resolve (value) {
        if (self.status === 'pending') {
            self.status = 'resolved'
            self.data = value
            for (let i = 0; i < self.onResolvedCallBack.length; i++) {
                self.onResolvedCallBack[i](value)
            }
        }
    }

    function reject (reason) {
        if (self.status === 'pending') {
            self.status = 'rejected'
            self.data = reason
            for (let i = 0; i < self.onRejectedCallBack.length; i++) {
                self.onRejectedCallBack[i](reason)
            }
        }
    }

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

_Promise.prototype.then = function (onResolved, onRejected) {
    const self = this
    let promise2 = undefined

    onResolved = typeof onResolved === 'function' ? onResolved : function (v) {return v}
    onRejected = typeof onRejected === 'function' ? onRejected : function (r) {throw r}

    if (self.status === 'resolved') {
        return promise2 = new _Promise(function (resolve, reject) {
            try {
                const x = onResolved(self.data)
                if (x instanceof _Promise) x.then(resolve, reject)
                resolve(x)
            } catch (e) {
                reject(e)
            }
        })
    }

    if (self.status === 'rejected') {
        return promise2 = new _Promise(function (resolve, reject) {
            try {
                const x = onRejected(self.data)
                if (x instanceof _Promise) x.then(resolve, reject)
            } catch (e) {
                reject(e)
            }
        })
    }

    if (self.status === 'pending') {
        return promise2 = new _Promise(function (resolve, reject) {
            self.onResolvedCallBack.push(function (value) {
                try {
                    const x = onResolved(self.data)
                    if (x instanceof _Promise) x.then(resolve, reject)
                } catch (e) {
                    reject(e)
                }
            })

            self.onRejectedCallBack.push(function (reason) {
                try {
                    const x = onRejected(self.data)
                    if (x instanceof _Promise) x.then(resolve, reject)
                } catch (e) {
                    reject(e)
                }
            })
        })
    }
}

_Promise.prototype.catch = function (onRejected) {
    return this.then(null, onRejected)
}

function resolvePromise (promise2, x, resolve, reject) {
    let then
    let thenCalledOrThrow = false

    if (x === promise2) return reject(new TypeError('Chaining cycle detected for promise!'))

    if (x instanceof _Promise) {
        if (x.status === 'pending') {
            x.then(function (value) {
                resolvePromise(promise2, vlaue, resolve, reject)
            }, reject)
        } else {
            x.then(resolve, reject)
        }
        return
    }

    if ((x !== null) && ((typeof x === 'object') || (typeof x === 'function'))) {
        try {
            then = x.then

            if (typeof x === 'function') {
                then.call(x, function rs(y) {
                    if (thenCalledOrThrow) return
                    thenCalledOrThrow = true
                    return resolvePromise(promise2, y, resolve, reject)
                }, function rj(r) {
                    if (thenCalledOrThrow) return
                    thenCalledOrThrow = true
                    return reject(r)
                })
            } else {
                resolve(x)
            }
        } catch (e) {
            if (thenCalledOrThrow) return
            thenCalledOrThrow = true
            return reject(e)
        }
    } else {
        resolve(x)
    }
}

const p = new _Promise(function (resolve, reject) {
    setTimeout(function () {
        resolve('p')
    })
})

const p2 = p.then(function (value) {
    // console.log(value)
})
console 命令行工具 X clear

                    
>
console