Promise静态方法的浅实现

Promise静态方法实现

承接上文 基于Promise A+ 浅实现Promise

实现过程中使用到的工具函数

/**
 * 判断传入值是否为一个 thenable对象 (可以访问 then方法 的对象)
 * @param { * } value 待判断的值
 * @returns { Boolean }
 */
function isThenable(value) {
    return (
        !isEqual(value, null) &&
        (judgmentType(value, "object") || judgmentType(value, "function")) &&
        judgmentType(handleTarget.then, "function")
    );
}
/**
 * 判断传入值是否为一个 promise对象 实例
 * @param { * } value 待判断的值
 * @returns { Boolean }
 */
function isPromise(value) {
    return value instanceof myPromise;
}

/**
 * 判断传入值和目标值是否相等
 * @param { * } value 待判断的值
 * @param { * } target 目标值
 * @returns { Boolean }
 */
function isEqual(value, target) {
    return value === target;
}
/**
 * 判断传入值和目标类型是否相等
 * @param { * } value 待判断的值
 * @param { * } type 目标类型
 * @param { Boolean } negation 是否取反判断
 * @returns { Boolean }
 */
function judgmentType(value, type, negation = false) {
    if (negation) {
        return typeof value !== type;
    }

    return typeof value === type;
}

Promise静态方法 resolve

  • Promise静态方法 resolve 可以将传入参数转换为一个Promise对象,根据参数的类型又作出不同的处理。

  • 参数类型——相应处理

  1. 如果参数本身为一个Promise对象,则直接返回该Promise对象。
  2. 如果参数是一个thenable对象,则调用其then方法以及相关联的两个回调函数。
  3. 如果参数不符合上述情况,待返的Promise对象将以该值兑现。
  • 在Promise静态方法 resolve的实现中,我们需要处理的点:根据参数类型作出相应操作返回一个Promise对象,支持链式调用

实现

class myPromise {





    ....




   /**
    * 根据参数类型,返回对应状态的Promise对象
    * @param { * } value 生成的Pormise对象结果值/返回的Promise对象
    * @returns { myPromise }
    */
    static resolve(value) {
        if (isPromise(value)) return value // 如果参数是Promise对象直接返回
        if (isThenable(value)) { // 如果参数是thenable对象,执行其then方法,并返回一个Promise对象
            return new myPromise((resolve, reject) => {
                value.then(resolve,reject)
            })
        }
        // 默认返回一个 fulfilled 状态的Promise对象 结果值为传入参数值
        return new myPromise((resolve, reject) => {
            resolve(value)
        })
    }
}

// 测试
            function p1() {
                return new Promise((resolve, reject) => {
                    resolve("p1 resolve");
                });
            }
            console.log(Promise.resolve(p1()));
            console.log(Promise.resolve("aa"));
            console.log(Promise.resolve([]));
            console.log(Promise.resolve(new Map()));
            console.log(Promise.resolve(p1));
            console.log(Promise.resolve({
                then(onFulfilled, onRejected) {
                    onFulfilled('thenable')
                }

            }));

image.png

Promise静态方法 reject

  • Promise静态方法 reject 无需参数类型的分类处理,统一返回一个rejected状态的Promise对象,结果值(拒因)为所传入的参数。

  • 在Promise静态方法 reject的实现中,我们需要处理的点:返回一个拒绝状态的Promise对象,支持链式调用

实现

class myPromise {





    ....




    /**



     * 返回一个以参数为拒因的rejected状态的Promise对象
     * @param { * } value 拒因
     * @returns { myPromise } 
     */




    static reject(value) {
        return new myPromise((resolve, reject) => {




            reject(value)
        })
    }
}
// 测试
            const p = myPromise.resolve(1);
            const rejected = myPromise.reject(p);
            console.log(rejected === p); // false
            rejected.then(undefined,(v) => {
                console.log(v === p); // true
            });
            myPromise.reject(new Error("失败")).then(
                () => {
                    // 不会被调用
                },
                (error) => {
                    console.error(error); // Stacktrace
                }

            );

image.png

Promise静态方法 all

  • Promise静态方法 all 接收一个可迭代对象作为输入,并返回一个Promise对象,当且仅当所有的迭代值(若值不是Promise对象,需要进行转换)都被兑现时,待返的Promise对象才会被兑现(即便传入的是一个空的迭代对象)。结果值为一个包含所有兑现值的数组。如果其中一个迭代值被拒绝,则待返对象的Promise对象会被拒绝,并带有第一个被拒绝的原因。

  • 在Promise静态方法 all 的实现中,我们需要处理的点:参数需要是一个可迭代对象返回Promise对象,支持链式调用转换不是Promise对象的迭代值为Promise对象根据迭代处理情况决定待返Promise对象的状态

实现

class myPromise {





    ....




    /**



     * 根据可迭代对象中迭代值的状态,决定待返Pormise对象的状态 (all fulfilled ---> fulfilled ) / (one rejected ---> rejected)
     * @param { iterable } promises 可迭代对象



     * @returns { myPromise }



     */




    static all(promises) {
        return new myPromise((resolve, reject) => {




            // 获取可迭代对象的长度/遍历可迭代对象 使用的语法 均只适配与可迭代对象
            // 如果在使用时产生报错 即说明用户传入的参数不是一个可迭代对象
            try {
                const length = [...promises].length // 获取可迭代对象的长度
                const resultList = [] // 待返结果值 存储迭代值的结果
                // 如果是一个空的可迭代对象 直接修改待返Promise对象的状态为 fulfilled,
                if (isEqual(length, 0)) return resolve(resultList) 
                let count = 0 // 遍历索引 
                for (const promiseItem of promises) {
                    // 迭代值可以为任何类型,但都需要转换成Promise对象,不同的类型又有不同的转换操作
                    // 这里使用Promise静态方法 resolve 来进行转换
                    myPromise.resolve(promiseItem).then(
                        (result) => {
                        // 当前迭代值为fulfilled,存储其结果
                            resultList[count++] = result // 存储完毕 索引后移
                            // 当索引等于可迭代对象的长度时,说明所有迭代值都为fulfilled,且所有结果都存储完毕,直接修改待返对象的状态为fulfilled
                            isEqual(count, length) && resolve(resultList)
                        },
                        (reason) => {
                        // 迭代值中只要有一个rejected,就直接修改待返对象的状态为rejected
                            reject(reason)
                        }
                    )
                }
            } catch(error) {
                // 用户传入的参数不是可迭代对象 直接修改待返对象的状态为rejected
                reject(new TypeError("Argument is not iterable"))
            }
        })
    }
}
// 测试
            const p1 = new myPromise((resolve, reject) => {
                resolve("p1 resolve");
            });
            const p2 = new myPromise((resolve, reject) => {
                resolve("p2 resolve");
            });
            const thenable = {
                then(onFulfilled, onRejected) {
                    onFulfilled("thenable resolve");
                },
            };
            const arr = [p1, p2, thenable];
            const map = new Map([
                [0, p1],
                [1, p2],
                [2, thenable],
            ]);
            const set = new Set([...arr]);
            console.log(myPromise.all(arr));
            console.log(myPromise.all(map));
            console.log(myPromise.all(set));

image.png

Promise静态方法 allSettled

  • Promise静态方法 allsettled 接收一个可迭代对象作为输入,并返回一个Promise对象。当所有的迭代值(若值不是Promise对象的,需要进行转换)都已敲定时(包括传入空的可迭代对象时),待返Promise对象将被兑现,结果值为一个个结构为{ status: ‘迭代值的状态’, value: ‘迭代值的结果值’ }的对象组成的数组。

  • 在Promise静态方法 allsettled 的实现中,我们需要处理的点有:参数需要是一个可迭代对象返回Promise对象,支持链式调用转换不是Promise对象的迭代值为Promise对象获取每个迭代值的结果值,用于返回

实现

class myPromise {





    ....




     /**
     * 返回一个fulfilled状态对象 结果值为一个个由 { status: '迭代值状态', value: '迭代值结果值' }结构组成的数组
     * @param { iterable } promises 可迭代对象



     * @returns { myPromise }



     */




    static allSettled(promises) {
        return new myPromise((resolve, reject) => {




            try {


                const length = [...promises].length

                const resultList = []
                if (isEqual(length, 0)) return resolve(resultList)
                let count = 0
                for (const promiseItem of promises) {
                    myPromise.resolve(promiseItem).then(
                        (result) => {
                        // 当前迭代值为fulfilled,存储其结果 存储完毕后 索引后移
                            resultList[count++] = {
                                status: 'fulfilled',
                                value: result
                            }
                            // 当索引等于可迭代对象的长度时,说明所有迭代值都为fulfilled,且所有结果都存储完毕,直接修改待返对象的状态为fulfilled
                            isEqual(count, length) && resolve(resultList)
                        },
                        (reason) => {
                            resultList[count++] = {
                                status: 'rejected',
                                value: reason
                            }
                            // 当索引等于可迭代对象的长度时,说明所有迭代值都为fulfilled,且所有结果都存储完毕,直接修改待返对象的状态为fulfilled
                            isEqual(count, length) && resolve(resultList)
                        }
                    )
                }

            } catch (error) {
                reject(new TypeError("Argument is not iterable"))
            }
        })
    }

}
// 测试
            const p1 = new myPromise((resolve, reject) => {
                resolve("p1 resolve");
            });
            const p2 = new myPromise((resolve, reject) => {
                reject("p2 reject");
            });
            const thenable = {
                then(onFulfilled, onRejected) {
                    onFulfilled("thenable resolve");
                },
            };
            const arr = [p1, p2, thenable];
            const map = new Map([
                [0, p1],
                [1, p2],
                [2, thenable],
            ]);
            const set = new Set([...arr]);
            console.log(myPromise.allSettled(arr));
            console.log(myPromise.allSettled(map));
            console.log(myPromise.allSettled(set));
            console.log(myPromise.allSettled("123456"));
            console.log(myPromise.allSettled(123456));

image.png

image.png

Promise静态方法 any

  • Promise静态方法 any 接收一个可迭代对象作为输入,并返回一个Promise对象。当迭代值中的任何一个被兑现时(若值不是Promise对象,需要进行转换),待返回的Promise对象将会被兑现,并返回第一个兑现的值。当所有迭代值都被拒绝时(包括传递了一个空的可迭代对象),它会以一个包含拒绝原因数组的 AggregateError 拒绝

  • 在Promise静态方法 any 的实现中,我们需要处理的点:参数需要是一个可迭代对象返回Promise对象,支持链式调用转换不是Promise对象的迭代值为Promise对象根据迭代处理情况决定待返Promise对象的状态

实现

class myPromise {





    ....




    /**



     * 根据可迭代对象中迭代值的状态,决定待返Pormise对象的状态 (one fulfilled ---> fulfilled ) / (all rejected ---> rejected)
     * @param { iterable } promises 可迭代对象



     * @returns { myPromise }



     */




    static any(promises) {
        return new myPromise((resolve, reject) => {




            try {


                const length = [...promises].length

                const reasonList = []  // 待返结果值 存储迭代值的结果
                // 如果是一个空的可迭代对象 直接修改待返Promise对象的状态为 rejected
                if(isEqual(length, 0)) return reject(new AggregateError(reasonList,"All promises were rejected"))
                let count = 0
                for (const promiseItem of promises) {
                    myPromise.resolve(promiseItem).then(
                    // 迭代值中只要有一个fulfilled,就直接修改待返对象的状态为fulfilled
                        (result) => resolve(result),
                        (reason) => {
                        // 当前迭代值为rejected,存储其结果(拒因)
                            reasonList[count++] = reason // 存储完毕 索引后移
                            // 当索引等于可迭代对象的长度时,说明所有迭代值都为rejected,且所有结果都存储完毕,直接修改待返对象的状态为rejected
                            isEqual(count, length) && reject(new AggregateError(reasonList,"All promises were rejected"))
                        }
                    )
                }

            } catch(error) {
                reject(new TypeError("Argument is not iterable"))
            }
        })
    }
}

// 测试
            const p1 = new myPromise((resolve, reject) => {
                resolve("p1 resolve");
            });
            const p3 = new myPromise((resolve, reject) => {
                setTimeout(() => {
                    resolve("p3 resolve");
                });
            });
            const p2 = new myPromise((resolve, reject) => {
                reject("p2 reject");
            });
            const thenable = {
                then(onFulfilled, onRejected) {
                    onFulfilled("thenable resolve");
                },
            };
            const arr = [p2, thenable, p3];
            const map = new Map([
                [0, p1],
                [1, p2],
                [2, thenable],
            ]);
            const set = new Set([...arr]);
            console.log(myPromise.any(arr));
            console.log(myPromise.any(map));
            console.log(myPromise.any("123456"));
            console.log(myPromise.any(123));

image.png

Promise静态方法 race

  • Promise静态方法 race 接收一个可迭代对象作为输入,并返回一个Promise对象。这个返回的Promise会随着第一个Promise的敲定而敲定。

  • 在Promise静态方法 race 的实现中,我们需要处理的点:参数需要是一个可迭代对象返回Promise对象,支持链式调用转换不是Promise对象的迭代值为Promise对象根据第一个迭代处理情况决定待返Promise对象的状态

实现

class myPromise {





    .....
    /**



     * 返回一个状态由迭代值中第一个状态敲定的对象决定的Pormise对象
     * @param { iterable } promises 可迭代对象



     * @returns { myPromise }



     */




    static race(promises) {
        return new myPromise((resolve, reject) => {




            try {


                for (const promiseItem of promises) {
                    myPromise.resolve(promiseItem).then(
                        (result) => resolve(result),
                        (reason) => reject(reason)
                    )
                }
            } catch (error) {
                reject(new TypeError("Argument is not iterable"))
            }
        })
    }
}
// 测试
            const p1 = new myPromise((resolve, reject) => {
                resolve("p1 resolve");
            });
            const p3 = new myPromise((resolve, reject) => {
                setTimeout(() => {
                    resolve("p3 resolve");
                });
            });
            const p2 = new myPromise((resolve, reject) => {
                reject("p2 reject");
            });
            const thenable = {
                then(onFulfilled, onRejected) {
                    onFulfilled("thenable resolve");
                },
            };
            const arr = [p2, thenable, p3];
            const map = new Map([
                [0, p1],
                [1, p2],
                [2, thenable],
            ]);
            const set = new Set([...arr]);
            console.log(myPromise.race(arr));
            console.log(myPromise.race(map));
            console.log(myPromise.race("123456"));
            console.log(myPromise.race(123));
            console.log(myPromise.race([]));

image.png

image.png

参考

手写实现 Promise 全部实例方法和静态方法,来看看 Promise.all、Promise.race 和 Promise.any 都是怎么实现的 – 掘金 (juejin.cn)

Promise – JavaScript | MDN (mozilla.org)

完整代码

© 版权声明
THE END
喜欢就支持一下吧
点赞0

Warning: mysqli_query(): (HY000/3): Error writing file '/tmp/MYnTfWHX' (Errcode: 28 - No space left on device) in /www/wwwroot/583.cn/wp-includes/class-wpdb.php on line 2345
admin的头像-五八三
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

图形验证码
取消
昵称代码图片