16-实现一个Promise.all 和 Promise.race

思路:首先明白Promise.all的用法

1:promise.all可以接受一个由promise数组作为参数,并且返回一个promise实例,

2:promise.all([a,b,c...]).then方法之后的结果是一个数组,返回的数组是参数中依次执行的返回值

3: 参数中的promise有一个失败则全部失败

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>

</html>
<script>
    // 检测传入的是不是promise对象
    function isPromise(fun) {
        return typeof fun.then === 'function'
    }

    var p1 = new Promise((reslove, reject) => {
        setTimeout(() => {
            reslove('p1')
        }, 1000)
    })
    var p2 = new Promise((reslove, reject) => {
        reslove('p2')
    })
    var p3 = 123456;
    var p4 = function() {
            return new Promise((reslove, reject) => {
                reject(new Error('我是一个错误'))
            })
        }
        // let res1 = isPromise(p1);
        // console.log(res1);
    Promise.myAll = function(arr) {
        return new Promise((reslove, reject) => {
            let count = 0;
            let resultArr = []; //存放传入的promise数组中每个promise执行结果的数组

            function sortFn(index, value) {
                // 每次执行+=1,用于计数
                count += 1;
                // resultArr不能直接push到数组中value的值,如果value是个数字,会排在第一位,影响顺序
                // 通过传进来的下标去指定位置,这样顺序就是我们想要的,极好!
                resultArr[index] = value;
                // 如果都成功了就把结果输出出去
                if (count === arr.length) {
                    // console.log(resultArr, "结果");
                    reslove(resultArr)
                }
            }

            // 遍历传进来的promise数组
            for (let i = 0; i < arr.length; i++) {
                let cur = arr[i];
                // 如果数组中当前的这一项是promise,那么就执行这个promise函数
                // 并且把执行结果(当前这个promise的索引和结果作为参数传递出去)
                if (isPromise(cur)) {
                    cur.then(res => {
                            sortFn(i, res);
                        }, reject) //reject就是外层的那个reject,因为只要有一个错误,就抛出
                }
                // 如果不是个promise函数,那么就把当前这一项的索引和其本身传递出去
                else {
                    sortFn(i, cur);
                }
            }
        })
    }

    Promise.myAll([p1, p2, p3, p4()]).then(res => {
            console.log(res);
        }, err => {
            console.log(err);
        })
        // 用.catch捕获,也可以向上面那样用then的第二个参数捕获错误
        // .catch(err => {
        //     console.log(err);
        // })
</script>

黄色标记get到思想:

1.为了使循环中的结果添加到newArr新数组中,正常情况下我们会用newArr.push的情况。但是如果传入的数组中不是promise对象,而是一个数字,比如123456,那么最后这个输出这个数组的顺序就变成了数字排在了前面,不符合我们想要的Promise.all的输出顺序。

2.所以我们需要手动保存当前循环中的索引,在上面newArr添加的时候,newArr[index] =value,我们通过存的索引,用数组的下标索引的方式去添加,这样就能保证添加顺序了。


 思路:Promise.race的用法:

1.Promise.race()里面也是放了一个数组,数组里面的谁快,谁先执行,执行的结果就是当下这个Promise.race([]).then(res) 这个res结果

2.不论数组里的结果成功还是失败,返回最快的那个结果。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>

<body>

</body>

</html>
<script>
    var p1 = new Promise((reslove, reject) => {
        setTimeout(() => {
            reslove('p1')
        }, 1000)
    })
    var p2 = new Promise((reslove, reject) => {
        setTimeout(() => {
            reslove('p2')
        }, 500)
    })
    var p3 = 123456;
    var p4 = new Promise((reslove, reject) => {
        setTimeout(() => {
            reject(new Error('这是一个错误'))
        }, 100)
    })
    var p5 = new Promise((reslove, reject) => {
        reslove('p5')
    })

    function isPromise(fun) {
        return typeof fun.then === 'function';
    }

    Promise.myRace = function(arr) {
        return new Promise((reslove, reject) => {
            for (let i = 0; i < arr.length; i++) {
                let cur = arr[i];
                if (isPromise(cur)) {
                    cur.then(res => {
                        // 谁先执行了,就把结果传出去
                        reslove(res)
                    }, reject)
                } else {
                    reslove(cur)
                }
            }
        })
    }

    Promise.myRace([p1, p2, p3, p4, p5]).then(res => {
            console.log(res);
        }, err => {
            console.log(err);
        })
        // 第二种写法:在外面调用catch
        // .catch(err => {
        //     console.log(err);
        // })


    // Promise.race([p1, p2, p3, p4, p5]).then(res => {
    //     console.log(res, '???');
    // }, err => {
    //     console.log(err);
    // })
</script>

一句话:在传入数组的循环中,执行每一项,谁最快有结果,就直接reslove把结果传递出去。

 

posted @ 2021-06-23 01:19  猎奇游渔  阅读(102)  评论(0编辑  收藏  举报