7.循环调用

44 阅读1分钟
// promise的循环调用
// 错误示例
// const promise = new Promise((resolve, reject) => {
//     resolve(100)
// })

// const p1 = promise.then(value => {
//     console.log(value)
//     return p1 // 报错 [TypeError: Chaining cycle detected for promise #<Promise>]
// })

// // 自己可以捕获到这种错误
// p1.then(() => {}, reason => {
//     console.log(reason) // [TypeError: Chaining cycle detected for promise #<Promise>]
// })

// 处理以上问题
const PENDING = 'pending'
const FUFILLED = 'fulfilled'
const REJECTED = 'rejected'

class MyPromise {
    constructor (executor) {
        executor(this.resolve, this.reject)
    }
    status = PENDING
    value = undefined
    reason = undefined
    successCallback = []
    failCallback = []

    resolve = value => {
        if (this.status !== PENDING) return
        this.status = FUFILLED
        this.value = value
        while(this.successCallback.length) this.successCallback.shift()(this.value)
    }
    reject = reason => {
        if (this.status !== PENDING) return
        this.status = REJECTED
        this.reason = reason
        while(this.failCallback.length) this.failCallback.shift()(this.reason)
    }
    then(successCallback, failCallback) {
        const promise2 = new MyPromise((resolve, reject) => {
            if (this.status === FUFILLED) {
                setTimeout(() => {
                    const successValue = successCallback(this.value)
                    // 改造成异步代码,否则promise2拿不到 会报错
                    resolvePromise(promise2, successValue, resolve, reject)
                }, 0)
            } else if (this.status === REJECTED) {
                failCallback(this.reason)
            } else {
                this.successCallback.push(successCallback)
                this.failCallback.push(failCallback)
            }
        })
        return promise2
    }
}
function resolvePromise(promise2, successValue, resolve, reject) {
    if (successValue === promise2) {
        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
    }
    if (successValue instanceof MyPromise) {
        successValue.then(value => resolve(value), reason => reject(reason))
    } else {
        resolve(successValue)
    }
}

// 验证
const mypromise =  new MyPromise((resolve, reject) => {
    resolve('successValue')
})

const p2 = mypromise.then(
    values => {
        console.log(values)
        return p2
    },
    reason => {
        console.log(reason)
    }
)

p2.then(() => {}, reason => {
    console.log(reason) // TypeError: Chaining cycle detected for promise #<Promise>
})