4.Promise链式调用的实现

Promise可以实现链式调用,既then之后可以接着使用then方法

let p = new Promise((resolve, reject) => {
    resolve('a')
})
p.then((value) => {
    return value
}, (reason) => {
    return reason
}).then((value) => {
    console.log(value) //a
})

分析
  • then的方法执行后返回一个Promise对象
  • then中onFulfilled或onRejected执行的结果会传入下一个Promise中
    • 如果then中onFulfilled或onRejected执行的结果为普通值,则作为下一个promise中的resolve执行
    • 如果为Promise,则令其then执行,直到为普通值,讲结果传入下一个Promise中的resolve或reject
    • 如果出错,则 reject
设计思路
  • 声明一个函数resolvePromise,专门处理上一个then中的onFulfilled或onRejected返回的的结果是否是Promise
  • then方法中新建一个Promise对象并返回
    • 将上一个onFulfilled或onRejected的执行放在下一个Promise中的executor中执行,这样方便获取其返回值
    • 返回的结果可能是新声明的Promise本身,所以也要判断一下
      • 同步无法先在executor中获取到声明的Promise对象,所以要改成异步
    • resolvePromise也可能出错,在外面加上try…catch
      • 出错直接走reject
const PENDING = "PENDING"
const FULFILLED = "FULFILLED"
const REJECTED = "REJECTED"

function resolvePromise (p, x, resolve, reject) {

}

class Promise {
    constructor(executor) {
        this.state = PENDING
        this.value = undefined
        this.reason = undefined
        this.resolveCallback = []
        this.rejectCallback = []
        const resolve = (value) => {
            //只有当状态是PENDING时才能改变状态
            if (this.state === PENDING) {
                this.state = FULFILLED
                this.value = value
                this.resolveCallback.forEach(fn => fn())
            }
        }
        const reject = (reason) => {

            if (this.state === PENDING) {
                this.state = REJECTED
                this.reason = reason
                this.rejectCallback.forEach(fn => fn())
            }
        }
        //,默认执行构造器
        try {
            executor(resolve, reject);
        } catch (e) {
            //如果出错这直接变成错误状态
            reject(e)
        }
    }
    then (onFulfilled, onRejected) {

        let p = new Promise((resolve, reject) => {
            if (this.state === FULFILLED) {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value)
                        resolvePromise(p, x, resolve, reject)
                    }
                    catch (e) {
                        reject(e)
                    }
                }, 0);

            }
            if (this.state === REJECTED) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(p, x, resolve, reject)
                    }
                    catch (e) {
                        reject(e)
                    }
                }, 0);
            }
            if (this.state === PENDING) {
                this.resolveCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onFulfilled(this.value)
                            resolvePromise(p, x, resolve, reject)
                        }
                        catch (e) {
                            reject(e)
                        }
                    }, 0);
                })
                this.rejectCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let x = onRejected(this.reason)
                            resolvePromise(p, x, resolve, reject)
                        }
                        catch (e) {
                            reject(e)
                        }
                    }, 0);
                })
            }
        })
		return p
    }

}

module.exports = Promise

resolvePromise的操作逻辑:

  • 判断是否是新创建的Promise对象本身,若是这直接reject
  • 判断是否为Promise对象若是,执行then方法
    • 执行完then之后若value或reason为普通值,执行resolv或reject
    • 若为promise,则继续递归resolvePromise
    • 出错直接reject
  • 若为常量,直接resolve
function resolvePromise (p, x, resolve, reject) {
    //若为其本身
    if (x === p) {
        //抛出错误
        reject(new Error('错误'))
    }
    if (typeof x === 'object' && x !== null || typeof x === 'function') {
        // 如果x是用户定义的Promise,为防止其规范,加上一个防护措施,防止状态二次改变
        let called = false
        // try一下,x即使有then方法也不一定能调用,defineProperty定义可以设置限制
        try {
            let then = x.then;
            //可以认为是Promise
            if (typeof then === 'function') {
                // 执行then,采用call执行,不宜直接调用,
                then.call(x, (value) => {
                    if (called) {
                        return;
                    }
                    called = true
                    //递归
                    resolvePromise(p, value, resolve, reject)
                }, (reason) => {
                    if (called) {
                        return
                    }
                    called = true
                    reject(reason)
                })
            } else {
                if (called)
                    return
                called = true
                resolve(x)
            }
        }
        catch (e) {
            reject(e)
        }
    }
    else {
        resolve(x)
    }
}

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

问也去

创作不易,感谢支持

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值