Promise的实现



/*
做之前先来看看我们promise的用法
*/

// let r = new Promise((resolve, reject) => {
//     resolve("成功")
// })

// r.then((res) => {
//     console.log(res)
// }, (err) => {
//     console.log(err)
// })
/**
 * 从上边的代码我们可以确定以下几件事
  1. Promise 就是一个类 在执行这个类的时候 需要传递一个执行器进去 执行器会立即执行
  2. Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending
    pending -> fulfilled
    pending -> rejected
    一旦状态确定就不可更改
  3. resolve和reject函数是用来更改状态的
    resolve: fulfilled
    reject: rejected
  4. then方法内部做的事情就判断状态 如果状态是成功 调用成功的回调函数 如果状态是失败 调用失败回调函数 then方法是被定义在原型对象中的
  5. then成功回调有一个参数 表示成功之后的值 then失败回调有一个参数 表示失败后的原因
  6. 同一个promise对象下面的then方法是可以被调用多次的
  7. then方法是可以被链式调用的, 后面then方法的回调函数拿到值的是上一个then方法的回调函数的返回值
 */

//接下来,我们先来简单实现上边功能,先把promise整体写个大概再来查缺补漏

// Promise 中有三种状态 分别为 成功 fulfilled 失败 rejected 等待 pending,所以我们可以全局定义3个变量,方便调用

const PENDING = 'pending';
const RESOLVE = 'resolve';
const REJECT = 'reject';
class MyPromise {

    // reject的实现是一样的,只是最后调用的是reject而不是resolve方法
    static resolve(value) {
        // 判断是否是thenable对象
        if (value instanceof MyPromise || ((typeof value === 'object') && 'then' in value)) {
            return value;
        }

        return new MyPromise((resolve) => resolve(value));//可以链式调用,所以要返回一个promise
    }

    static reject(value) {
        // 判断是否是thenable对象
        if (value instanceof MyPromise || ((typeof value === 'object') && 'then' in value)) {
            return value;
        }

        return new MyPromise((reject) => reject(value));
    }
    static all(arr) {
        let res = [] //结果
        let num = 0 //看看是不是所有任务都执行完了
        return new MyPromise((resolve, reject) => {
            function addData(index, data) {
                res[index] = data
                num++;;
                if (num === arr.length) {
                    //执行完就给结果
                    resolve(res)
                }
            }
            for (let i = 0; i < arr.length; i++) {
                let current = arr[i]//当前任务
                if (current instanceof MyPromise) {
                    current.then((value) => { addData(i, value) }, (e) => { reject(e) })
                } else {
                    addData(i, current)
                }
            }
        })
    }

    static race(arr) {
        return new MyPromise((resolve, reject) => {
            for (let i = 0; i < arr.length; i++) {
                let current = arr[i]//当前任务
                // 这里使用 Promise.resolve 包了一下,以防传递了 non-promise
                Promise.resolve(current).then(res => {
                    resolve(res);
                }, error => {
                    reject(error);
                });
            }
        })
    }
    constructor(fn) {
        /*
          new Promise , 需要传递一个执行器进去 执行器会立即执行,fn就是这个执行器,
          可以看到应用的时候fn是会有两个方法回传回去的,分别是resolve和reject函数,所以我们来实现这两个方法
        */
        fn(this.resolve, this.reject)
    }
    // 成功之后的值
    value = undefined;
    // 失败后的原因
    reason = undefined;
    // promsie 状态 
    status = PENDING;
    //成功的异步回调
    successCallback = [];
    //失败的异步回调
    failCallback = [];
    //为了保证调用的时候this指向永远都指向类本身,这里用箭头函数的形式来定义
    // resolve和reject函数是用来更改状态的
    //resolve在调用的时候会接收一个值,用于返回给then第一个回调的参数,所以我们得定义一个变量(value),用于接收这个参数
    resolve = (value) => {
        //首先状态不可逆,所以先判断promise状态
        if (this.status !== PENDING) return;
        //接收resolve的值,等待then的调用
        this.value = value
        //接下来就是改状态了,resolve是成功,
        this.status = RESOLVE
        //调用成功的异步回调
        this.successCallback.map(item => item && item())
    }
    //reject在调用的时候会接收一个值,用于返回给then第二个回调的参数,所以我们得定义一个变量(reason),用于接收这个参数
    reject = (reason) => {
        //首先状态不可逆,所以先判断promise状态
        if (this.status !== PENDING) return;
        //接收reject的值,等待then的调用
        this.reason = reason
        //接下来就是改状态了,reject是成功,
        this.status = REJECT
        //调用失败的异步回调
        this.failCallback.map(item => item && item())
    }
    finally(callback) {
        //会返回一个promise对象
        return this.then(value => {
            return MyPromise.resolve(callback()).then(() => value);
        }, reason => {
            return MyPromise.resolve(callback()).then(() => { throw reason })
        })
    }
    catch(failCallback) {
        return this.then(undefined, failCallback)
    }
    /*
        接下来实现then,then接收两个参数,分别是成功的回调和失败的回调
     */
    then(resolveCallBack, rejectCallBack) {
        // 参数可选
        resolveCallBack = resolveCallBack ? resolveCallBack : value => value;
        // 参数可选
        rejectCallBack = rejectCallBack ? rejectCallBack : value => { throw value };
        //then方法要实现链式调用就得返回一个新的promise对象
        let promise2 = new MyPromise((resolve, reject) => {
            //判断promise状态,来决定调用哪个方法
            if (this.status === RESOLVE) {
                setTimeout(() => {
                    try {
                        let r = resolveCallBack(this.value)
                        // 在then中的会返回值会作为下一次then的参数,所以这里封装了一个方法来调用
                        //为了在这里拿到promise2的值,所以用了定时器做了异步处理
                        //这里传promise2的目的是为了处理then返回自身promise的情况,做了一个报错处理
                        /* resolvePromise函数的作用
                         // 判断 x 的值是普通值还是promise对象
                        // 如果是普通值 直接调用resolve 
                        // 如果是promise对象 查看promsie对象返回的结果 
                        // 再根据promise对象返回的结果 决定调用resolve 还是调用reject
                        */
                        resolvePromise(promise2, r, RESOLVE, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            } else if (this.status === REJECT) {
                setTimeout(() => {
                    try {

                        let r = rejectCallBack(this.reason)

                        resolvePromise(promise2, r, REJECT, resolve, reject)
                    } catch (error) {
                        reject(error)
                    }
                }, 0)
            } else {
                //处理异步代码
                this.successCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let r = resolveCallBack(this.value);
                            resolvePromise(promise2, r, RESOLVE, resolve, reject)
                        } catch (e) {
                            reject(e);
                        }
                    }, 0)
                })
                this.failCallback.push(() => {
                    setTimeout(() => {
                        try {
                            let r = rejectCallBack(this.reason);
                            resolvePromise(promise2, r, REJECT, resolve, reject)
                        } catch (e) {
                            reject(e);
                        }
                    }, 0)
                })
            }
        })

        return promise2

    }
}
function resolvePromise(promise2, r, status, resolve, reject) {
    if (promise2 === r) {
        return reject(new TypeError("Chaining cycle detected for promise #<Promise>"))

    }
    if (r instanceof MyPromise) {
        r.then(resolve, reject)
    } else {
        if (status === RESOLVE) {
            resolve(r)
        } else {
            reject(r)
        }
    }

}
//测试用例1(基本功能)
//以上我们就完成了promise的基本功能,接下来我们看看我们自己的promise和原生的promise的测试结果是否一致

// let myPromise1 = new MyPromise((resolve, reject) => {
//     resolve("myPromise1成功")
//     reject("myPromise1失败")
// })
// myPromise1.then((res) => {
//     console.log(res)
// }, (err) => {
//     console.log(err)
// })

//测试用例2(promise中加入异步逻辑)

//在用例1中我们实现了promise的基本逻辑,接下来我们就来看看promise中加入异步逻辑怎么实现
/*
    如用例2我们在定时器里resolve,有了异步代码,但按照我们用例1的代码肯定是无法做到和原生一样的
    我们在then方法中还没有判断状态为pending的时候,因此我们应该定义两个数组,一个用来接收成功的的异步逻辑回调
    一个用来接收失败的异步逻辑回调,在resolve或reject的时候来执行这些回调
*/

// let myPromise2 = new MyPromise((resolve, reject) => {
//     setTimeout(() => {
//         resolve("myPromise2成功")
//     }, 10)
//     // reject("myPromise2失败")
// })
// myPromise2.then((res) => {
//     console.log(res)
// }, (err) => {
//     console.log(err)
// })


//测试用例3(then的链式调用)
//注要实现then的链式调用,then方法的可选参数,错误捕获
// let myPromise3 = new MyPromise((resolve, reject) => {
//     setTimeout(() => {
//         resolve("myPromise3成功")
//     }, 10)
//     reject("myPromise3失败")
// })
// myPromise3.then((res) => {
//     console.log(res)
//     return "first"
// }, (err) => {
//     console.log(err)
//     return "失败"
// }).then((res) => {
//     console.log(res)
//     return "two"
// }, (err) => {
//     console.log(err)
// }).finally(()=>{
//     console.log("finally")
// }).catch((err)=>{
//     console.log(err,"catch")
// })


//测试用例4(静态方法的实现)

//promise.resolve()
MyPromise.resolve("myPromise4成功").then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})

//promise.reject()
MyPromise.reject("myPromise4失败").then((res) => {
    console.log(res)
}, (err) => {
    console.log(err)
})

//promise.all()
function p1() {
    return new MyPromise(function (resolve, reject) {
        setTimeout(function () {
            resolve('成功1')
        }, 4000)
    })
}
function p2() {
    return new MyPromise(function (resolve, reject) {
        //reject('失败')

        setTimeout(function () {
            resolve('成功2');
        }, 3000)
    })
}

MyPromise.all([1, 2, p1(), p2(), 6]).then((res) => {
    console.log(res, 'promise.all res')
}, (err) => {
    console.log(err, 'promise.all err')
})

MyPromise.race([p1(), p2()]).then((res) => {
    console.log(res, 'promise.race res')
}, (err) => {
    console.log(err, 'promise.all err')
})
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享