手写实现自己的Promise

141 阅读3分钟

Promise是es6的新特性,在我们的项目开发过程中经常会用到,但是平时用的时候,可能就是知其然而不知其所以然,下面,我们就来实现一个自己promise

const fulfilled = 'fulfilled'
const rejected = 'rejected'
const pending = 'pending'

function resolvePromise(promise2, x, resolve, reject) {
    if (promise2 === x) {
        throw new Error('类型错误')
    }
    //判断x是一个普通值还是一个promise
    if ((typeof x === 'object' && x !== null) || typeof x === 'function') {
        // console.log('x:',  x.then());
        try {
            let then = x.then;
            //说明x是一个promise
            if (then && typeof then === 'function') {
                //执行then方法,this指向X ,成功的回调函数有可能又是一个promise
                then.call(x, (y) => {
                    resolvePromise(promise2, y, resolve, reject)
                    // resolve(y);
                }, (r) => {
                    reject(r)
                })
            } else {
                resolve(x)
            }
        } catch (e) {
            reject(e)
        }
    } else {
        resolve(x)
    }
}

class Promise {
    constructor(executor) {
        this.status = pending
        this.value = ''       //存储成功的原因
        this.reason = ''      //存储失败的原因
        this.successFn = []    //保存成功的回调
        this.failFn = []       //保存失败的回调
        let resolve = (value) => {
            if (this.status === pending) {
                this.status = fulfilled
                //这个value有可能是一个promise
                this.value = value
                if (this.successFn.length > 0) {
                    this.successFn.forEach(fn => fn(this.value))
                }
            }
        }
        let reject = (reason) => {
            if (this.status === pending) {
                this.status = rejected
                this.reason = reason
                if (this.failFn.length > 0) {
                    this.failFn.forEach(fn => fn(this.reason))
                }
            }
        }
        try {
            executor(resolve, reject)
        } catch (e) {
            if (this.status === pending) {
                this.status = rejected
                this.reason = e
            }
        }
    }

    catch(err) {
        return this.then(null, err)
    }

    then(onFulfilled, onRejected) {
        // 参数的可选
        onFulfilled = typeof onFulfilled === 'function' ? onFulfilled : val => val
        onRejected = typeof onRejected == 'function' ? onRejected : err => {
            throw err
        }
        let promise2 = new Promise((resolve, reject) => {
            if (this.status === pending) {
                onFulfilled && this.successFn.push(() => {
                    try {
                        let x = onFulfilled(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }

                })
                onRejected && this.failFn.push(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                })
            }
            if (this.status === fulfilled) {
                setTimeout(() => {
                    try {
                        let x = onFulfilled(this.value)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }
                }, 0)
            }
            if (this.status === rejected) {
                setTimeout(() => {
                    try {
                        let x = onRejected(this.reason)
                        resolvePromise(promise2, x, resolve, reject)
                    } catch (e) {
                        reject(e)
                    }

                }, 0)

            }
        })

        return promise2
    }

    resolve(value) {
        return new Promise((res, rej) => {
            res(value)
        })
    }

    reject(err) {
        return new Promise((res, rej) => {
            rej(err)
        })
    }

    static resolve(value) {
        return new Promise((res, rej) => {
            res(value)
        })
    }

    static reject(err) {
        return new Promise((res, rej) => {
            rej(err)
        })
    }
    
    //finally方法
    finally(callback) {
        callback()
        return this.then(res => {
            return this.resolve(res)
        }, err => {
            return this.reject(err)
        })
    }
    //race方法
    static race(args) {
        return new Promise((resolve,reject) =>{
                for (let i = 0; i < args.length; i++) {
                if (isPromise(args[i])) {
                    args[i].then(res=>{
                        resolve(res)
                    },err =>{
                        reject(err)
                    })
                } else {
                    //如果不是promise 直接成功
                    resolve(args[i])
                }
            }
        })
    }
}
//promise的all方法
Promise.all = function(promises){
    return new Promise((resolve,reject)=>{
        let arr = [];//返回的数组
        let i = 0 ;
        let processData = (index,data) =>{
            arr[index]= data;
            if(++i === promises.length ){
                resolve(arr)
            }
        }

        for(let i = 0 ; i< promises.length ; i++){
            let current = promises[i];
            if(isPromise(current)){
                current.then(data =>{
                    processData(i,data)
                },reject)
                
            }else {
                processData(i,current)
            }
        }
    })
}

function isPromise(fn) {
    if ((typeof fn === 'object' && fn !== null) || typeof fn === 'function') {
        return fn.then && typeof fn.then === 'function'
    }
    return false
}

export default Promise

下面是我们的测试文件:

import PromiseMy from './promise'
let p =new PromiseMy((resolve,reject)=>{
    resolve('你好啊')
})
// let m = PromiseMy.reject('errrrr')
// m.then((res)=>{
//     console.log('res:',res)
// },err =>{
//     console.log('err:',err)
// })

// let k = new PromiseMy((resolve,reject)  =>{
//     resolve('dasdasd')
// })
// k.then(res =>{
//     console.log('res1:',res);
//     return '50000'
// },err =>{
//
// }).finally(res =>{
//     setTimeout(()=>{
//         console.log('finally:',res)
//
//     },2000)
// }).then(res =>{
//     console.log('then2:',res)
// })
//
// PromiseMy.race([12,3,4])
// p .then(res=>{
//     console.log('res:',res)
//     return new PromiseMy((resolve,reject) =>{
//         resolve(new PromiseMy((resolve,reject) =>{
//             setTimeout(()=>{
//                 resolve('jajdasds')
//             },1000)
//         }))
//     })
// }).then(res =>{
//     console.log('res2:',res)
// }).catch(err =>{
//     console.log('我的catrch方法:',err)
// })
//
// let m = Promise.reject('wocao')
// m.then(res =>{
//     console.log('m1:',res)
// },err =>{
//     console.log('m:',err)
// })


let p1 = new PromiseMy((resolve,reject) =>{
    setTimeout(()=>{
        resolve('成功了1')
    },2000)
})

let p2 = new PromiseMy((resolve,reject) =>{
    setTimeout(()=>{
        resolve('成功了2')
    },1000)
})

PromiseMy.race([p1,p2]).then(res =>{
    console.log('race res :',res)
},err=>{
    console.log('race err :,',err)
})

/*
*
*    let p = new PromiseMy((resolve, reject) => {
                // console.log(xxxx)
                reject('你好啊')
            })
            // .catch(err=>{
            //     console.log('err:',err)
            // }).then(data=>{
            //     console.log('data:',data)
            // })
            // let m = PromiseMy.reject('errrrr')
            // m.then((res)=>{
            //     console.log('res:',res)
            // },err =>{
            //     console.log('err:',err)
            // })

            let k = new PromiseMy((resolve,reject)  =>{
                resolve('dasdasd')
            })
            k.then(res =>{
                console.log('res1:',res);
                return '50000'
            },err =>{

            }).finally(res =>{
                setTimeout(()=>{
                    console.log('finally:',res)

                },2000)
            }).then(res =>{
                console.log('then2:',res)
            })

            // PromiseMy.race([12,3,4])
    /*        p .then(res=>{
                console.log('res:',res)
                return new PromiseMy((resolve,reject) =>{
                    resolve(new PromiseMy((resolve,reject) =>{
                        setTimeout(()=>{
                            resolve(new PromiseMy((res,rej)=>{
                                res('ldaskdlsafjsahdkjashdjkash')
                            }))
                        },1000)
                    }))
                })
            }).then(res =>{
                console.log('res2:',res)
            }).catch(err =>{
                return new PromiseMy((resolve,reject) =>{
                    resolve(new PromiseMy((resolve,reject) =>{
                        setTimeout(()=>{
                            reject(new PromiseMy((res,rej)=>{
                                res('ldaskdlsafjsahdkjashdjkash')
                            }))
                            // resolve('12312312')
                        },1000)
                    }))
                })
            }).then(err =>{
                console.log('err:',err)
            })*/
//
// let m = Promise.reject('wocao')
// m.then(res =>{
//     console.log('m1:',res)
// },err =>{
//     console.log('m:',err)
// })
//
// let p1 = new PromiseMy((resolve, reject) => {
//     setTimeout(() => {
//         resolve('成功了1')
//     }, 2000)
// })
//
// let p2 = new PromiseMy((resolve, reject) => {
//     setTimeout(() => {
//         resolve('成功了2')
//     }, 1000)
// })
// //
// PromiseMy.race([p1, p2]).then(res => {
//     console.log('race res :', res)
// }, err => {
//     console.log('race err :,', err)
// })*/

经过测试可以发现,promise的链式调用以及一些原型上面的方法或者静态方法都已经实现了