JS-精简的Promise实现

为了更好的体现Promise的核心实现,已决状态只留resolved

参数值传递

new myPromise(resolve => {
    resolve(12)
}).then(data => {
    console.log(data)
})
复制代码

看myPromise内需要传一个函数,且该函数的参数还是个函数,即这种形式myPromise(fn(f)),f里有一个参数。之后then中的data会被赋予f中的参数值,then()需要传递一个函数作为参数,而data又是该函数的参数。
要实现这样的数据传递,如何做?

myPromise以类的方式声明

class myPromise {
    constructor(excu) {
        this.data = 0
        let resolve = dat => {
            this.data = dat
        }
        excu(resolve)
    }
    then(thennable) {
        thennable(this.data)
    }
}
复制代码

一、值在类中被保存

  1. 在constructor中,该类需要传递一个函数作为参数,即constructor(excu),excu中有一个resolve函数,最后excu需要在new的时候被执行一次,即excu(resolve)
  2. 在该类中resolve是没有被定义的,需要定义。形式上resolve有个参数,需要被保存用data保存

二、值传递到then中

  1. 定义then方法,在then方法传递一个thennable参数
  2. then方法内,调用thennable(this.data)

且看效果

new myPromise((resolve, reject) => {
    resolve(12)
}).then(data => {
    console.log(data)
})
//打印出12
复制代码

解释:js中的值传递可以实参到形参,也可以形参到实参,貌似并没有明确的界限,很灵活thennable(this.data),将data值传到了then(data => {console.log(data)})处。

then的链式调用实现

先将代码推到这一步

class myPromise {
    constructor(excu) {
        this.data = 0
        this.status = "pendding"
        let resolve = dat => {
            if (this.status == "pendding") {
                this.data = dat
                this.status = "resolved"
            }
        }
        excu(resolve)
    }
    then(thennable) {
        let promise2 = new myPromise(resolve => {
            if (this.status == "resolved") {
                let x = thennable(this.data)
                resolve(x)
            }
        })
        return promise2
    }
}
复制代码

加入状态padding和resolved不用多说了,主要看then函数中的变化。

  1. then返回的得是个promise,因此需要new myPromise,再return。
  2. thennable是有返回值的,这里不考虑复杂情况,假设返回的仅仅是一个数字。那么该数字即成为下一个promise的data值。
  3. 用resolve完成关联,注意此处的resolve是new myPromise中的参数,换句话说,resolve是then生成的新promise的,而箭头函数的使用,使得其中的this指向前一个promise,最后resolve(x),将前Promise的data值成功传递到了后Promise的data中

且看效果

new myPromise((resolve, reject) => {
    resolve(12)
}).then(data => {
    console.log(data)
    return data
}).then(data => {
    console.log(data + 1)
    return data + 1
}).then(data => {
    console.log(data + 1)
    return data + 1
})
/*打印结果:
12
13
14
*/
复制代码

thennable队列的实现

  1. myPromise中,padding状态不能执行thennable中的代码
  2. 切换为resolved状态后,才能执行thennable中的代码
  3. 采用一个数组进行存储resolved状态要执行的函数
  4. 在resolve函数中执行先前存储的函数
class myPromise {
    constructor(excu) {
        this.data = 0
        this.status = "pendding"
        this.arrayResolve = []
        let resolve = dat => {
            if (this.status == "pendding") {
                this.data = dat
                this.status = "resolved"
                //将压入arrayResolve的函数拿出运行
                this.arrayResolve.forEach(fn => fn())
                //其实该数组最多只有一项,也可以使用一下代码执行
                // if(this.arrayResolve[0]!=undefined){//也可以try...catch
                //     this.arrayResolve[0]()
                // }
            }
        }
        excu(resolve)
    }
    then(thennable) {
        let promise2 = new myPromise(resolve => {
            if (this.status == "resolved") {
                console.log("resolved")
                //加setTimeout模拟异步
                setTimeout(() => {
                    let x = thennable(this.data)
                    resolve(x)
                }, 0)
            }
            //添加内容
            //如果当前promise状态为pendding,则用存储resolved状态运行的代码。
            if (this.status == "pendding") {
                console.log("pendding")
                this.arrayResolve.push(() => {
                    setTimeout(() => {
                        let x = thennable(this.data)
                        resolve(x)
                    }, 0)
                })
            }
        })
        return promise2
    }
}

//测试代码:
new myPromise((resolve, reject) => {
    // setTimeout(() => {
        resolve(12)
    // }, 1)
}).then(data => {
    console.log(data)
    return data
}).then(data => {
    console.log(data + 1)
    return data + 1
}).then(data => {
    console.log(data + 1)
    return data + 1
})
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享