14_2.手写Promise

start

  • 花了两个小时手写了一个Promise,也算是说做就做,没有拖延。
  • 不管写的好坏与否,对Promise掌握程度还是有很大提升,写完的感受就很爽。(*^▽^*)
  • 暂时就写完整版吧,相关思路注释写的很详细了。

Promise.js

// 1 创建一个 函数 叫  Promise
function Promise(executor) {

    // 3 实例上有几个属性
    this.PromiseState = 'pending'
    this.PromiseResult = undefined
    this.callBack = []
    let that = this

    // 4 匿名函数有两个参数 也是函数 当他们执行的时候,去修改状态和输出结果
    function resolve(data) {
        // 6 实例状态只能修改一次
        if (that.PromiseState !== 'pending') return

        that.PromiseState = 'fulfilled'
        that.PromiseResult = data


        // 25 ① then的返回值修改为异步的
        setTimeout(() => {
            that.callBack.forEach(element => {
                element.resolved(that.PromiseResult)
            });
        })
    }

    function reject(data) {
        if (that.PromiseState !== 'pending') return

        that.PromiseState = 'rejected'
        that.PromiseResult = data

        // 25 ②
        setTimeout(() => {
            that.callBack.forEach(element => {
                element.rejected(that.PromiseResult)
            });
        })

    }


    // 5 处理一下 匿名函数运行的异常,如果有错误,直接reject
    try {
        // 2 Promise接受一个参数可以执行
        executor(resolve, reject)
    } catch (error) {
        reject(error)
    }

}




// 7 实例的then方法
Promise.prototype.then = function (resolved, rejected) {

    // 17 兼容 then 参数可以为 0个 1个 两个 的写法
    if (typeof resolved !== 'function') { onResolved = value => value; }
    if (typeof rejected !== 'function') { onRejected = reason => { throw reason; } }


    let that = this
    /**  11:
    *    1. then方法返回的也是一个 Promise对象
    *    2. 返回一个什么样的Promise对象呢?
    *       + 如果本身就返回的一个Promise对象,就不做改变直接返回
    *       + 如果是`非Promise对象`,就返回一个状态为成功,值为这个 `非Promise对象` 的一个Promise对象
    *       + 如果 返回值是一个异常,就返回一个状态为失败,值为异常信息 的一个Promise对象
    *    
    *    3. 我这里在想在代码最后直接return一个promise对象不可以吗? 包裹起来比较好,取值以及异步逻辑都有优点??
    *    4. 为了方便区分,不和then接收的参数混淆,我在返回的Promise对象的参数前面加了 `to`
    */

    return new Promise(function (toResolve, toReject) {

        // 16 都是try catch 所以抽取公共方法; 执行的不一样所以type作为参数 
        function callBack(type) {
            try {
                let result = type(that.PromiseResult)
                if (result instanceof Promise) {
                    result.then(v => { toResolve(v); }, r => { toReject(r); })
                } else {
                    toResolve(result)
                }
            } catch (error) {
                toReject(error)
            }
        }


        // 8 then中可以传递两个参数 根据实例的状态去做执行
        if (that.PromiseState === 'fulfilled') {
            // try {
            //     // 9 如果执行then方法时,状态都已经改变了
            //     let result = resolved(this.PromiseResult)

            //     if (result instanceof Promise) {
            //         result.then(v => { toResolve(v); }, r => { toReject(r); })
            //     } else {
            //         toResolve(result)
            //     }
            // } catch (error) {
            //     toReject(error)
            // }
            // 25  ③ 
            setTimeout(() => {
                callBack(resolved)
            })
        }

        if (that.PromiseState === 'rejected') {
            // // 14 异常处理 范湖
            // try {
            //     // 13 处理一下then方法的返回值(只需要toResolve, toReject这两个方法执行即可)     这里的   rejected(this.PromiseResult)  ===  function (this.PromiseResult) {console.log(2, err)}
            //     let result = rejected(this.PromiseResult)

            //     //  13.① 返回原本的Promise对象  (如果本身就返回的一个Promise对象,我们递归调用then方法 然后获取这个promise的状态然后返回)
            //     if (result instanceof Promise) {
            //         result.then(v => { toResolve(v); }, r => { toReject(r); })
            //     } else {
            //         // 13 ②
            //         toResolve(result)
            //     }
            // } catch (error) {
            //     toReject(error)
            // }

            // 25  ④
            setTimeout(() => {
                callBack(rejected)
            })
        }

        //   10 如果状态是 pending(如果执行then方法时,状态未改变)就等后续 状态改变的时候再去执行对应的方法,这里存储到实例的属性 数组callBack 中
        if (that.PromiseState === 'pending') {
            that.callBack.push({
                // 15 pending 的函数怎么处理
                resolved: function () {
                    callBack(resolved)
                },
                rejected: function () {
                    callBack(rejected)
                }
            })
        }

    })

}

// 18 实例的catch方法
Promise.prototype.catch = function (onRejected) {
    return this.then(undefined, onRejected);
}


// 19 实例的finally方法 ---其实就是 在finally中的语句 会在then catch都执行一遍,所以返回一个then方法即可
Promise.prototype.finally = function (fn) {
    return this.then(data => { // then返回的也是一个Promise对象
        fn(); // 执行回调,但不传递数据
        return data; // 保证返回的Promise对象的数据一致
    }, reason => {
        fn();
        throw reason; // 保证返回的Promise对象的数据状态一致
    })

}



// 20 构造函数自身的方法 resolve
Promise.resolve = function (value) {
    /**
     * 参数
     * Ⅰ-如果为promise:将其状态与结果赋值给外层promise对象
     * Ⅱ-如果为非promise: 状态设置为成功,直接返回
    */
    return new Promise(function (toResolve, toReject) {
        if (value instanceof Promise) {
            value.then(v => { toResolve(v) }, r => { toReject(r) })
        } else {
            toResolve(value)
        }
    })
}


// 21 构造函数自身的方法 reject
Promise.reject = function (value) {
    /**
     * 参数
     * Ⅰ-如果为promise:将其状态与结果赋值给外层promise对象
     * Ⅱ-如果为非promise:状态设置为失败
    */
    return new Promise(function (toResolve, toReject) {
        if (value instanceof Promise) {
            value.then(v => { toResolve(v) }, r => { toReject(r) })
        } else {
            toReject(value)
        }
    })
}


// 22 Promise.all
Promise.all = function (promises) {
    /**  
     *  Promise.all([1,2,3])
     * 
     * (1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
     * (2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
    */

    return new Promise(function (toResolve, toReject) {
        let count = 0;
        let arr = [];
        for (let i = 0; i < promises.length; i++) {
            let value = promises[i]

            // 如果传入的不是promsie对象 给它转换为promise对象
            if (!(value instanceof Promise)) {
                value = Promise.resolve(value)
            }

            value.then(v => {
                count++;
                arr[i] = v;
                if (count === promises.length) {
                    // 所有的成功了 就直接返回
                    toResolve(arr);
                }
            }, r => {
                // 只要失败就直接返回
                toReject(r)
            })
        }

    })
}


// 23 Promise.allSettled 
Promise.allSettled = function (promises) {

    return new Promise(function (toResolve, toReject) {
        let count = 0;
        let arr = [];
        for (let i = 0; i < promises.length; i++) {
            let value = promises[i]

            // 如果传入的不是promsie对象 给它转换为promise对象
            if (!(value instanceof Promise)) {
                value = Promise.resolve(value)
            }

            value.then(v => {
                count++;
                arr[i] = {
                    status: 'fulfilled', value: v
                }
                if (count === promises.length) {
                    toResolve(arr);
                }
            }, r => {
                count++;
                arr[i] = {
                    status: 'rejected', reason: r
                }
                if (count === promises.length) {
                    toResolve(arr);
                }
            })
        }

    })

}


//  24 Promise.race 
Promise.race = function (promises) {
    // 谁先执行就返回谁的运行结果
    return new Promise((resolve, reject) => {
        for (let i = 0; i < promises.length; i++) {

            let value = promises[i]

            // 如果传入的不是promsie对象 给它转换为promise对象
            if (!(value instanceof Promise)) {
                value = Promise.resolve(value)
            }
            value.then(v => {
                resolve(v);
            }, r => {
                reject(r);
            })
        }
    });
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

lazy_tomato

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值