Promise用法

new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve('success')
    }, 1000)
}).then(res => {
    console.log(res) // 输出success
})

从代码里可以看出Promise构造函数接受一个匿名函数,匿名函数有两个参数,这两个参数也是函数。
打印出来的结果如下图:
image.png
可以观察到在resolve回调之前,Promise有一个pending状态;查看文档我们知道Promise有三个状态:pending(默认状态:等待),fulfilled(已成功),rejected(已拒绝)。
现在我们来尝试写一个自己的Promise

手写Promise

1、创建构造函数MyPromise,参数为一个函数fn
2、fn有两个参数,分别是成功(resolve)和拒绝(reject)的回调函数
3、resolve函数保存成功的值,reject函数保存失败原因
4、MyPromise实例原型需提供一个then函数供实例调用
5、then函数参数为一个匿名函数,该函数必须在resolve或reject之后执行

function MyPromise(fn) {
    // 默认状态为 pending
    this.state = 'pending'
    let self = this
    function resolve(value) {
        // 保存成功的值并将状态设为 resolved
        self.value = value
        self.state = 'resolved'
    }
    function reject(reason) {
        self.reason = reason
        self.state = 'rejected'
    }
    fn(resolve, reject);
}

MyPromise.prototype.then = function(onFinish) {
    if (this.state === 'resolved') {
        onFinish(this.value)
    }
    if (this.state === 'rejected') {
        onFinish(this.reason)
    }
}

写到这里我们写一段代码测试一下

var p = new MyPromise((resolve, reject) => {
    setTimeout(() => {
       resolve(1) 
    }, 1000)
})

p.then(res => {
    console.log(res)
})

发现没有输出打印结果,原因是setTimeout为异步代码,then函数先于resolve和reject函数执行。
为了确保then函数里面的函数在resolve和reject之后执行,我们可以将其存储起来,resolve和reject执行之后再执行该函数。

function MyPromise(fn) {
    // 默认状态为 pending
    this.state = 'pending'
    this.resolveStack = []
    this.rejectStack = []
    let self = this
    function resolve(value) {
        // 保存成功的值并将状态设为 resolved
        if (self.state === 'pending') {
           self.value = value
           self.state = 'resolved'
           self.resolveStack.forEach(cb => {
            cb(self.value)
           })   
        }
    }
    function reject(reason) {
        if (self.state === 'pending') {
            self.reason = reason
            self.state = 'rejected'
            self.rejectStack.forEach(cb => {
                cb(self.reason)
            })   
        }
    }
    fn(resolve, reject);
}

MyPromise.prototype.then = function(onFinish) {
    if (this.state === 'pending') {
        this.resolveStack.push(onFinish)
        this.rejectStack.push(onFinish)
    }
    if (this.state === 'resolved') {
        onFinish(this.value)
    }
    if (this.state === 'rejected') {
        onFinish(this.reason)
    }
}

var p = new MyPromise((resolve, reject) => {
    setTimeout(() => {
       resolve(1) 
    }, 1000)
})

p.then(res => {
    console.log(res)
})

到这里,一个Promise就差不多完成了。。。


前端茅台
14 声望0 粉丝

喜欢茅台的前端开发