Promise源码实现

Promise

一、promise的简单使用

new Promise((resolve, reject) => {
    resolve("ok")
}).then(data => {
    console.log(data) //OK
}, error => {
    console.log(error)
})
//简化下
let promise = new Promise(executor)
promise.then(onFulfilled, onRejected)
需要注意的是
  • executor是一个会被立即执行的回调函数, 该函数带有两个参数,resolve reject
  • 如果executor中调用了resolve(value) ,那么这个value则会被传给onFulfilled, 如第一个例子中console.log(data) 输出为ok
  • 如果executor中调用了reject(value) ,那么这个value则会被传给onRejected,作为onRejected的实参
  • 还有一点需要注意的是,promise是带有状态的,开始默认为pending,当调用resolve后,状态变更为fulFilled,当调用reject后,状态变更为rejected。当状态从pending变更为fulFilled / reject后,状态不可再改变

二、Promise 的初级实现

让我们继续带着第一个用例 来做个promise的初级实现
new Promise((resolve, reject) => {
    resolve("ok")
}).then(data => {
    console.log(data) //OK
}, error => {
    console.log(error)
})

// 我们带着例子逐行实现
// let executor = (resolve, reject) => { resolve("ok") }
// new Promise(executor)
class Promise {
    constructor(executor){
        this.status = "pending" //状态默认为等待态
        //executor = (resolve, reject) => { resolve("ok") }
        //传入的executor是一个带有两个参数的函数,
        //并且参数resolve和reject都是可调用的函数
        //所以我们应该先声明这两个函数 然后当成实参传入 executor
        const resolve = (value) => {
            
        }
        const reject = (error) => {
            
        }
        executor(resolve,reject)
    }
    
}
// let executor = (resolve, reject) => { resolve("ok") }
// new Promise(executor)
class Promise {
    constructor(executor){
        this.status = "penging"
        this.resValue = null
        this.rejValue = null
        // executor = (resolve, reject) => { resolve("ok") }
        const resolve = (value) => {
            // 如 resolve("ok") 中传入的"ok" 
            // 需要在后面代码的then的onFulilled中拿,故需要存储这个 value 
            this.resValue = value
            // 并且调用resolve后,状态更改为fulfilled
            if(this.status === "pending"){
                this.status = "fulfilled"
            }
        }
        const reject = (error) => {
            this.rejValue = error
            if(this.status === "pending"){
                this.status = "rejected"
            }
        }
        executor(resolve,reject)
    }
    
}
// let promise = new Promise(executor)
// promise.then(onFulfilled, onRejected)
// 可以得出 promise 需要一个 then 方法
class Promise {
    constructor(executor){
        // 如上...
    }
    then(onFulfilled, onRejected){
        //调用then方法的时候,要判断是当前状态是成功还是失败
        if(this.status === "fulfilled"){
            //如果当前是成功态
            onFulfilled(this.value)
        }
        if(this.status === "rejected"){
            //如果当前是失败态
            onRejected(this.error)
        }
    }
}
这样算是基本完成了promise 的初级功能,但是当 new promise(executor)传入的 executor为异步函数的时候,就会出现问题。如下:
new Promise((resolve,reject)=>{
    setTimeout(()=>{
       resolve("ok") 
    },0)
}).then(data => {
    console.log(data) //不会输出ok
})
// 其原因是:当 executor为异步函数传入new Promise`时
// 虽然立即调用了executor,但是其为异步函数,会被推入微任务,不会马上执行
// 所以下面这个resolve 不会马上执行,会先执行宏任务的 then 方法
// 所以在执行then 方法的时候,promise的状态仍然为 pending
class Promise {
    constructor(executor){
        // executor = setTimeout(()=>{resolve("ok")},0)
        const resolve = (value) => {
            // ** 2. 后执行
            this.value = value
            if(status === "pending"){
                this.status = "fulfilled"
            }
        }
        // ...
        executor(resolve,reject)
    }
    then(onFulfilled, onRejected){
        // ** 1. 先执行
        if(this.status === "fulfilled"){
            onFulfilled(this.value)
        }
        // ...
    } 
}

Promise 的初级实现之异步改进

现在的问题是, 在传入异步函数的时候,我们执行到 then方法的时候, 状态还是为 pending,所以无法执行到 onFulfilled。我们又需要在 executor 中调用了 resolve后执行 onFulfilled。所以很自然的想到了使用发布订阅模式来解决。即在 then中判断到当前为等待态时(那 executor一定是异步函数), 将 onFulfilledonRejected存起来, 在 executor中执行到resolve后 执行 onFulfilled。 下面是代码实现:
class Promise {
    constructor(executor){
        this.status = "pending"
        //onFulfilled集合
        this.onFulfilledCallbacks = [ ]
        //onRejected集合
        this.onRejectedCallbacks = [ ]
        
        const resolve = (value) => {
            this.resValue = value
            if(status === "pending"){
                this.status = "fulfilled"
                // 发布
                this.onFulfilledCallbacks.forEach(callback => {
                    callback(this.value)
                })
            }
        }
        const reject = (error) => {
            this.rejValue = error
            if(status === "pending"){
                this.status = "rejected"
                this.onRejectedCallbacks.forEach(callback => {
                    callback(this.error)
                })
            }
        }
        executor(resolve,reject)
    }
    then(onFulfilled, onRejected){
        // 同步代码不变,增加异步情况代码
        if(this.status === "fulfilled"){
            onFulfilled(this.value)
        }
        if(this.status === "rejected"){
            onRejected(this.error)
        }
        // 新增代码
        if(this.status === "pending"){
            // 已经到then了,status的状态还没有改变。
            // 说明 executor 中为异步函数
            // 订阅
            this.onFulfilledCallbacks.push((data)=>{
                //切片
                onFulfilled(data)
            })
            this.onRejectedCallbacks.push((error)=>{
                onRejected(error)
            })
        }
        
    }
}
以上就是promise 的初级实现,promise的核心在于他们链式调用。我们在下一章详细介绍

三、了解promise的链式调用

    new Promise((resolve,reject) => {
        resolve("hello")
    }).then(data => {
        console.log(data) //hello
        return "world"
    }).then(data => {
        console.log(data) //world
    })
如果在then 中 return一个简单值(非 promise),那么将在下一个 then 中的 onFulfilled取到这个值。
    new Promise((resolve,reject) => {
        resolve("hello")
    }).then(data => {
        throw new Error()
    }).then(data => {
        console.log(data) 
    },error => {
        console.log(error) // Error
    })
如果在then中抛出异常,那么将会在下一个then的 onRejected拿到这个异常。
    let promise1 = new Promise((resolve,reject) => {
        resolve("hello")
    }).then(data => {
        return data
    })
    
    console.log(promise1) // Promise{: "hello"}
    // 可以看得出来: 在then方法中,会返回一个promise对象
    // 因为promise的状态不可二次改变, 所以返回的应该是一个新的promise对象

四、测试案例分析

在完成promise的链式调用前, 首先要有个测试案例:

let promise1 = new Promise((resolve, reject) => {
    setTimeout(() => {
        resolve("the message is ")
    }, 0);
})
let promise2 = promise1.then(data => {
    let interPromise = new Promise((resolve,reject) => {
        setTimeout(() => {
            resolve(data + "that today is a happy day")
        }, 0);
    })
    return interPromise
}, null)
我觉得有必要先分析下这个 promise2
  • 1.首先我们知道这个promise1.then()一定是返回一个新的promise,而且是一个带着完成或结束态的promise
  • 2.所以在then的内部生成一个promise,并且在内部完成了这个promiseresolve(data),而且这个data来之内部的interPromiseresolve()
  • 3.再看下这个interPromise, 他要想把内部的resolve(data + "that today is a happy day")里的数据传给上层thenpromise,那么只能是隐性的调用interPromisethen,并且在这个then中, 调用上层promiseresolve
  • 这是promise中的最难点,如果没看懂,可以多看几遍,懵懂的话可以先看下面的代码实现,再回过头来看这段分析
let promise3 = promise2.then(data => {
    console.log(data) // expect: the message is that today is a happy day
})

六、promise的链式调用

该案例为了方便阅读和理解,就实现了最难的功能,并且省略了异常捕获等内容。
// constructor不变,只对then方法进行了修改
class Promise {
    constructor(executor) {
        this.status = "pending"
        this.resValue = null
        this.rejValue = null
        this.onfulfilledCallbacks = []
        this.onrejectedCallbacks = []
        const resolve = (value) => {
            this.resValue = value
            if (this.status === "pending") {
                this.status = "fulfilled"
                this.onfulfilledCallbacks.forEach(callback => {
                    callback(this.resValue)
                })
            }
        }
        const reject = (error) => {
            this.rejValue = value
            if (this.status === "pending") {
                this.status = "rejected"
                this.onrejectedCallbacks.forEach(callback => {
                    callback(this.rejValue)
                })
            }
        }
        executor(resolve, reject)
    }
    then(onFulfilled, onRejected) {
        // onFulfilled = data => new Promise(...)
        //then 方法返回promise2
        const promise2 = new Promise( (resolve2,reject2) => {
            if (this.status === "pending") {
                //async 
                //这里需要一个实现一个异步
                //因为在resolvePromise中需要 完成初始化的promise2
                setTimeout(()=>{
                    this.onfulfilledCallbacks.push(data => {
                        //代入案例来看
                        //这个x = interPromise
                        let x = onFulfilled(data)
                        //然后判断这个x 是否是一个 promise
                        resolvePromise(x, resolve2, reject2)
                    })
                    
                    this.onrejectedCallbacks.push(error => {
                        // 类比上面进行修改,这里不做修改
                        onRejected(error)
                    }) 
                },0)
            }
            // 下面情况和上面同理,我不做修改
            if (this.status === "fulfilled") {
                onFulfilled(this.resValue)
            }
            if (this.status === "rejected") {
                onRejected(this.rejValue)
            }
            
        })
        return promise2
    }
}

function resolvePromise(x, resolve2, reject2){
    // 源码中有许多判断的异常捕获,这里就实现最核心的代码
    if((typeof x === "object" && typeof x !== "null")|| typeof x === "function"){
        // x is a object or function
        let then = x.then
        if(typeof then === "function"){
            // 在这里调用interPromise的then 
            // 并且调用上层promise的resolve
            then.call(x,data => resolve2(data),null)
            // x is a promise
            // for example: x = new promise((resolve,reject) => {resolve("ok")})
        }
    }
}

你可能感兴趣的:(javascript,promise)