1. 今日一題 - 請(qǐng)模擬實(shí)現(xiàn)一個(gè)Promise.all() 方法?

        共 5122字,需瀏覽 11分鐘

         ·

        2021-01-24 11:09

        對(duì)Promise.all 的理解

        Promise.all()方法用于將多個(gè) Promise 實(shí)例,包裝成一個(gè)新的 Promise 實(shí)例。

        Promise.all()方法的參數(shù)可以不是數(shù)組,但必須具有 Iterator 接口(所以數(shù)組、Map、Set都可以),并且只返回一個(gè)Promise實(shí)例,輸入的所有promise的resolve回調(diào)的結(jié)果會(huì)按傳入的按順序作為一個(gè)數(shù)組的其中一項(xiàng)返回。

        當(dāng)然也支持非promise對(duì)象的傳入,會(huì)作為數(shù)組中的一項(xiàng)返回。

        返回結(jié)果的兩個(gè)特點(diǎn)

        全部成功一起返回:當(dāng)接收的所有Promise實(shí)例都執(zhí)行成功后才會(huì)返回結(jié)果,返回的結(jié)果是一個(gè)數(shù)組,返回值將會(huì)按照參數(shù)內(nèi)的 promise 順序排列,而不是由調(diào)用 promise 的完成順序決定。

        失敗快速返回:當(dāng)其中一個(gè)Promise實(shí)例執(zhí)行失敗了就會(huì)立刻返回,只返回失敗的結(jié)果,不會(huì)管其他promise執(zhí)行的結(jié)果。

        使用方式 - promise 實(shí)例全部成功一起返回

        let?p1?=?new?Promise((resolve,?reject)?=>?{
        ??resolve('p1')
        })
        let?p2?=?new?Promise((resolve,?reject)?=>?{
        ??resolve('p2')
        })

        let?p3?=?new?Promise((resolve,?reject)?=>?{
        ??resolve('p3')
        })


        //全部成功的情況,接收p1?p2,?p3
        Promise.all([p1,?p2,?p3]).then(results?=>?{
        ??console.log(results)
        }).catch(error?=>?{
        ??console.log(error)
        })

        使用方式 - 失敗快速返回

        即便是最后一個(gè)promise 失敗了,也會(huì)提前返回,不會(huì)等待前面的promise返回.

        var?p1?=?new?Promise((resolve,?reject)?=>?{
        ??setTimeout(resolve,?1000,?'one');
        });
        var?p2?=?new?Promise((resolve,?reject)?=>?{
        ??setTimeout(resolve,?2000,?'two');
        });
        var?p3?=?new?Promise((resolve,?reject)?=>?{
        ??setTimeout(resolve,?3000,?'three');
        });
        var?p4?=?new?Promise((resolve,?reject)?=>?{
        ??setTimeout(resolve,?4000,?'four');
        });
        var?p5?=?new?Promise((resolve,?reject)?=>?{
        ??reject('reject');
        });

        Promise.all([p1,?p2,?p3,?p4,?p5]).then(values?=>?{
        ??console.log(values);
        },?reason?=>?{
        ??console.log(reason)
        });

        如果傳入的是非promise對(duì)象呢?

        如果參數(shù)中包含非 promise 值,這些值將被忽略,但仍然會(huì)被放在返回?cái)?shù)組中.

        var?p?=?Promise.all([1,2,3]);
        var?p2?=?Promise.all([1,2,3,?Promise.resolve(4)]);
        var?p3?=?Promise.all([1,2,3,?Promise.reject(5)]);
        setTimeout(function(){
        ????p.then(res=>console.log(res))
        ?????p2.then(res=>console.log(res))
        ?????p3.then(res=>console.log(res))
        });

        錯(cuò)誤處理

        因?yàn)镻roims.all() 結(jié)果返回的是一個(gè) promise對(duì)象,所以和普通的promise錯(cuò)誤處理是一樣的。

        可以通過reject或者catch來進(jìn)行捕獲。

        ?//1?catch
        ?//....
        ?Promise.all([p1,?p2,p3]).then(results?=>?{
        ????console.log(results)????//?['p1',?'p2']
        ??}).catch(error?=>?{
        ????//錯(cuò)誤捕獲
        ????console.log(error)
        ??})
        ??
        ?//2?reject
        ?//....
        ?Promise.all([p1,?p2,p3]).then(results?=>?{
        ????console.log(results)????//?['p1',?'p2']
        ??},(error){
        ?//錯(cuò)誤捕獲
        ??console.log(error)
        })

        模擬實(shí)現(xiàn)

        上面的幾個(gè)特點(diǎn)就是我們思考的入口,也是必須要滿足的條件。

        • 多個(gè)promise最后返回一個(gè)promise
        • 必須全部成功才會(huì)返回
        • 失敗會(huì)優(yōu)先返回,不會(huì)等他promise結(jié)果
        ?function?customerPromiseAll(promises)?{
        ????return?new?Promise((resolve,?reject)?=>?{
        ??????let?resultCount?=?0;?//計(jì)數(shù)器
        ??????let?promiseLen?=?promises.length;?//傳入的promise個(gè)數(shù)
        ??????let?results?=?new?Array(promiseLen);//初始化數(shù)組用于存放返回結(jié)果
        ?
        ??????//按順序執(zhí)行
        ??????for?(let?i?=?0;?i?????????promises[i].then(value?=>?{
        ??????????resultCount++;
        ??????????results[i]?=?value;?//保證執(zhí)行結(jié)果的順序
        ??????????if?(resultCount?===?promises.length)?{
        ????????????return?resolve(results)?//執(zhí)行完最后一個(gè)promise,則返回
        ??????????}
        ????????},?error?=>?{
        ??????????reject(error)?//執(zhí)行錯(cuò)誤直接reject
        ????????})
        ??????}
        ????})
        ??}

        驗(yàn)證一下

        ??let?p1?=?new?Promise(resolve?=>?resolve('p1'))
        ??let?p2?=?new?Promise(resolve?=>?resolve('p2'))
        ??let?p3?=?Promise.reject('p3?error')

        ??customerPromiseAll([p1,?p2]).then(results?=>?{
        ????console.log(results)????//?['p1',?'p2']
        ??}).catch(error?=>?{
        ????console.log(error)
        ??})

        ??customerPromiseAll([p1,?p2,?p3]).then(results?=>?{
        ????console.log(results)
        ??}).catch(error?=>?{
        ????console.log(error)??????//?'p3?error'
        ??})

        驗(yàn)證通過,結(jié)果沒啥毛病,符合預(yù)期。

        支持非promise對(duì)象

        上面我們驗(yàn)證傳入都是常規(guī)的promise對(duì)象,如果傳入非promise對(duì)象呢?

        customerPromiseAll([1,2,3])?//emmm?.直接報(bào)錯(cuò)了

        所以我們需要增加驗(yàn)證傳入的值是不是promise,非promise對(duì)象,則直接resolve。

        //驗(yàn)證是否是promise對(duì)象
        function?isPromise(obj)?{
        ??return?!!obj??//有實(shí)際含義的變量才執(zhí)行方法,變量null,undefined和''空串都為false
        ???&&?(typeof?obj?===?'object'?||?typeof?obj?===?'function')?//?初始promise?或?promise.then返回的
        ???&&?typeof?obj.then?===?'function';
        }

        完整代碼 1 非promise 對(duì)下直接存入數(shù)組

        function?customerPromiseAll(promises)?{
        ????return?new?Promise((resolve,reject)=>{
        ????????let?resultCount?=?0;
        ????????//計(jì)數(shù)器
        ????????let?promiseLen?=?promises.length;
        ????????//傳入的promise個(gè)數(shù)
        ????????let?results?=?new?Array(promiseLen);
        ????????//初始化數(shù)組用于存放返回結(jié)果

        ????????//按順序執(zhí)行
        ????????for?(let?i?=?0;?i?????????????if?(!isPromise(promises[i]))?{
        ????????????????resultCount++;
        ????????????????results[i]?=?promises[i];?//直接存儲(chǔ)結(jié)果

        ????????????????if?(resultCount?===?promiseLen)?{
        ????????????????????return?resolve(results)
        ????????????????????//執(zhí)行完最后一個(gè)promise,則返回
        ????????????????}
        ????????????}?else?{
        ????????????????promises[i].then(value=>{
        ????????????????????resultCount++;
        ????????????????????results[i]?=?value;?//存儲(chǔ)resolve的結(jié)果
        ????????????????????//保證執(zhí)行結(jié)果的順序
        ????????????????????if?(resultCount?===?promiseLen)?{
        ????????????????????????return?resolve(results)
        ????????????????????????//執(zhí)行完最后一個(gè)promise,則返回
        ????????????????????}
        ????????????????}
        ????????????????,?error=>{
        ????????????????????reject(error)
        ????????????????????//執(zhí)行錯(cuò)誤直接reject
        ????????????????}
        ???????????????)

        ????????????}
        ????????}
        ????}
        ???)
        }

        完整代碼2 非promise對(duì)象調(diào)用Promise.resolve()返回一個(gè)promise對(duì)象

        function?customerPromiseAll(promises)?{
        ????return?new?Promise((resolve,reject)=>{
        ????????let?resultCount?=?0;
        ????????//計(jì)數(shù)器
        ????????let?promiseLen?=?promises.length;
        ????????//傳入的promise個(gè)數(shù)
        ????????let?results?=?new?Array(promiseLen);
        ????????//初始化數(shù)組用于存放返回結(jié)果

        ????????//按順序執(zhí)行
        ????????for?(let?i?=?0;?i?????????????let?curPromise?=?promises[i]
        ????????????if?(!isPromise(curPromise))?{
        ????????????????curPromise?=?Promise.resolve(curPromise)
        ????????????}
        ????????????curPromise.then(value=>{
        ????????????????resultCount++;
        ????????????????results[i]?=?value;
        ????????????????//存儲(chǔ)resolve的結(jié)果
        ????????????????//保證執(zhí)行結(jié)果的順序
        ????????????????if?(resultCount?===?promiseLen)?{
        ????????????????????return?resolve(results)
        ????????????????????//執(zhí)行完最后一個(gè)promise,則返回
        ????????????????}
        ????????????}
        ????????????,?error=>{
        ????????????????reject(error)
        ????????????????//執(zhí)行錯(cuò)誤直接reject
        ????????????}
        ???????????)

        ????????}
        ????}
        ???)
        }

        最后

        平時(shí)對(duì)Promise.all方法只是處于使用的層面,其實(shí)深挖一下的話收獲還是很多的。

        今天就到這里,希望對(duì)你有用。

        點(diǎn)個(gè)『在看』支持下?

        瀏覽 60
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 我要操逼网站 | 在线视频亚洲一区 | 嗯~啊你轻点好深啊h王爷漫画 | 午夜精品18 视频国产 | 久久视频精品 |