<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          一道簡(jiǎn)單又有意思的 JavaScript 手寫(xiě)題 — 異步加法 asyncAdd

          共 4751字,需瀏覽 10分鐘

           ·

          2022-10-15 03:19

          前言

          在掘金上發(fā)現(xiàn)一道既簡(jiǎn)單但個(gè)人覺(jué)得還挺有意思的一道題,題目如下:

                //?異步加法
          function?asyncAdd(a,b,cb){
          ??setTimeout(()?=>?{
          ????cb(null,?a?+?b)
          ??},?Math.random()?*?1000)
          }

          async?function?total(){
          ??const?res1?=?await?sum(1,2,3,4,5,6,4)
          ??const?res2?=?await?sum(1,2,3,4,5,6,4)
          ??return?[res1,?res2]
          }

          total()

          //?實(shí)現(xiàn)下 sum 函數(shù)。注意不能使用加法,在 sum 中借助 asyncAdd 完成加法。盡可能的優(yōu)化這個(gè)方法的時(shí)間。
          function?sum(){

          }
          復(fù)制代碼

          你可以直接嘗試實(shí)現(xiàn)下,考察下自己的思維和 JavaScript 基礎(chǔ)知識(shí)的聯(lián)系如何,大佬請(qǐng)繞行!11d8a47c325705ded5894c9c9aa5a876.webp

          估計(jì)大多數(shù)人第一眼看下都不知道這題目到底要干啥(我不說(shuō)就沒(méi)人知道我也是),但是在看第二遍的時(shí)候估計(jì)就差不多明白具體是要考察什么內(nèi)容了,下面就一起來(lái)分析分析吧?。?!

          ae318abb9381682e96442cc4846b2d46.webp14040709.jpg 分析 asyncAdd

          這里先放置最終結(jié)論:

          • 只能修改 sum 部分的內(nèi)容,sum 可接收任意長(zhǎng)度的參數(shù)
          • sum 中只能通過(guò) asyncAdd 實(shí)現(xiàn)加法計(jì)算
          • sum 中需要處理異步邏輯,需要使用 Promise
          • 需要優(yōu)化 sum 方法的計(jì)算時(shí)間

          下面是分別通過(guò)對(duì)代碼的不同部分進(jìn)行分析,獲取到的相關(guān)的信息。

          直觀的基本要求

                //?實(shí)現(xiàn)下 sum 函數(shù)。注意不能使用加法,在 sum 中借助 asyncAdd 完成加法。盡可能的優(yōu)化這個(gè)方法的時(shí)間。?
          function?sum(){?}
          復(fù)制代碼

          最直觀的方式就是通過(guò)上述的文字描述部分,可以很容易知道題目具體要求:

          • 實(shí)現(xiàn) sum 函數(shù),即只能修改 sum 部分的內(nèi)容
          • 不能直接使用加法(+),通過(guò) asyncAdd 實(shí)現(xiàn)加法
          • 優(yōu)化 sum 方法的計(jì)算時(shí)間

          隱藏的考察點(diǎn) — setTimeout & cb

                //?異步加法
          function?asyncAdd(a,?b,?cb){
          ??setTimeout(()?=>?{
          ????cb(null,?a?+?b)
          ??},?Math.random()?*?1000)
          }
          復(fù)制代碼

          從上述內(nèi)容來(lái)看,最明顯的就是 setTimeoutcb 了,其實(shí)這不難理解因?yàn)樵?asyncAdd 中使用了 setTimeout 只能通過(guò)回調(diào)函數(shù) cb 將本次計(jì)算結(jié)果返回出去,那其中的第一個(gè)參數(shù) null 代表什么呢?其實(shí)可以認(rèn)為它是一個(gè)錯(cuò)誤信息對(duì)象,如果你比較了解 node 的話(huà),就會(huì)知道在 node 中的異步處理的回調(diào)函數(shù)通常第一個(gè)參數(shù)就是錯(cuò)誤對(duì)象,用于傳遞給外部在發(fā)生錯(cuò)誤時(shí)自定義后續(xù)執(zhí)行邏輯等。

          一句話(huà)cb 函數(shù)會(huì)接收 錯(cuò)誤對(duì)象計(jì)算結(jié)果 作為參數(shù)傳遞給外部。

          隱藏的考察點(diǎn) — async & await

                async?function?total(){
          ??const?res1?=?await?sum(1,2,3,4,5,6,4)
          ??const?res2?=?await?sum(1,2,3,4,5,6,4)
          ??return?[res1,?res2]
          }
          復(fù)制代碼

          從上述的這部分來(lái)看,**sum** 方法的 返回值 肯定是一個(gè) promise 類(lèi)型的,因?yàn)樽钋懊婷黠@的使用了 await sum(...) 的形式。

          另外 total 函數(shù)返回值也必然是一個(gè) promise 類(lèi)型,因?yàn)檎麄€(gè) total 函數(shù)被定義為了一個(gè) async 異步函數(shù),**可點(diǎn)擊此處查看詳細(xì)內(nèi)容**[2]。

          一句話(huà)sum 需要返回 promise 類(lèi)型的值,即 sum 一定會(huì)使用到 promise,并且從 sum(1,2,3,4,5,6,4) 可知 sum 可接收任意長(zhǎng)度的參數(shù)。

          實(shí)現(xiàn) asyncAdd

          題目的實(shí)現(xiàn)方式并不唯一,但核心點(diǎn)仍舊是考察你對(duì) JavaScript 異步操作方面的思考和實(shí)現(xiàn),以下只是給出了一種直觀的解決方式,算是 拋磚引玉,可以將你的最優(yōu)解貢獻(xiàn)在評(píng)論區(qū)!

          具體實(shí)現(xiàn)

          實(shí)現(xiàn)思路如下:

          • 考慮到外部參數(shù)長(zhǎng)度不固定,使用剩余運(yùn)算符接收所有傳入的參數(shù)
          • 考慮到 asyncAdd 中的異步操作,將其封裝為 Promise 的實(shí)現(xiàn),即 caculate 函數(shù)
          • 考慮到 asyncAdd 實(shí)際只能一次接收兩個(gè)數(shù)字進(jìn)行計(jì)算,使用循環(huán)的形式將多個(gè)參數(shù)分別傳入
          • 考慮到通過(guò)循環(huán)處理異步操作的順序問(wèn)題,使用 async/await 來(lái)保證正確的執(zhí)行順序,且 async 函數(shù)的返回值正好符合 sumPromise 類(lèi)型的要求

          具體代碼如下:

                //?通過(guò)?ES6?的剩余運(yùn)算符(...)?接收外部傳入長(zhǎng)度不固定的參數(shù)
          async?function?sum(...nums:?number[])?{
          ????//?封裝?Promise?
          ????function?caculate(num1:?number,?num2:?number)?{
          ????????return?new?Promise((resolve,?reject)?=>?{
          ????????????//?調(diào)用?asyncAdd?實(shí)現(xiàn)加法
          ????????????asyncAdd(num1,?num2,?(err:?any,?rs:?number)?=>?{
          ????????????????//?處理錯(cuò)誤邏輯
          ????????????????if?(err)?{
          ????????????????????reject(err);
          ????????????????????return;
          ????????????????}
          ????????????????//?向外部傳遞對(duì)應(yīng)的計(jì)算結(jié)果
          ????????????????resolve(rs);
          ????????????});
          ????????})
          ????}

          ????let?res:?any?=?0;
          ????
          ????//?通過(guò)遍歷將參數(shù)一個(gè)個(gè)進(jìn)行計(jì)算
          ????for?(const?n?of?nums)?{
          ????????//?為了避免異步執(zhí)行順序問(wèn)題,使用?await?等待執(zhí)行結(jié)果?
          ????????res?=?await?caculate(res,?n);
          ????}

          ????return?res;
          }
          復(fù)制代碼

          進(jìn)行優(yōu)化

          抽離內(nèi)層函數(shù)

          • caculate 函數(shù)可抽離到 sum 函數(shù)外層
          • asyncAdd 函數(shù)的回調(diào)函數(shù)沒(méi)必要抽離,因?yàn)樗蕾?lài)的參數(shù)和外部方法太多
                function?caculate(num1:?number,?num2:?number)?{
          ????return?new?Promise((resolve,?reject)?=>?{
          ????????asyncAdd(num1,?num2,?(err:?any,?rs:?number)?=>?{
          ????????????if?(err)?{
          ????????????????reject(err);
          ????????????????return;
          ????????????}
          ????????????resolve(rs);
          ????????});
          ????})
          }

          async?function?sum(...nums:?number[])?{
          ????let?res:?any?=?0;

          ????for?(const?n?of?nums)?{
          ????????res?=?await?caculate(res,?n);
          ????}

          ????return?res;
          }
          復(fù)制代碼

          緩存計(jì)算結(jié)果

          其實(shí)你仔細(xì)觀察 total 方法,其中 sum 調(diào)用了兩次,而且參數(shù)還是一模一樣的,目的就是提示你在第二次計(jì)算相同內(nèi)容時(shí)結(jié)果直接 從緩存中獲取,而不是在通過(guò)異步計(jì)算。

                async?function?total(){
          ??const?res1?=?await?sum(1,2,3,4,5,6,4)
          ??const?res2?=?await?sum(1,2,3,4,5,6,4)
          ??return?[res1,?res2]
          }
          復(fù)制代碼

          以下只是一個(gè)簡(jiǎn)單的緩存方案的實(shí)現(xiàn),不必過(guò)于糾結(jié),具體實(shí)現(xiàn)如下:

                const?cash:?any?=?{};

          function?isUndefined(target:?any)?{
          ????return?target?===?void?0;
          }

          async?function?sum(...nums:?number[])?{
          ????let?res:?any?=?0;
          ????const?key?=?nums.join('+');

          ????if?(!isUndefined(cash[key]))?return?cash[key];

          ????for?(const?n?of?nums)?{
          ????????res?=?await?caculate(res,?n);
          ????}

          ????cash[key]?=?res;

          ????return?res;
          }

          function?caculate(num1:?number,?num2:?number)?{
          ????return?new?Promise((resolve,?reject)?=>?{
          ????????asyncAdd(num1,?num2,?(err:?any,?rs:?number)?=>?{
          ????????????if?(err)?{
          ????????????????reject(err);
          ????????????????return;
          ????????????}
          ????????????resolve(rs);
          ????????});
          ????})
          }
          復(fù)制代碼


          關(guān)于本文

          作者:熊的貓

          https://juejin.cn/post/7134583899597832200

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  午夜久久久久久 | 国产强 暴 疼 哭 处 女 国产肉体ⅩXXX137大胆 | 日产一区二区三区视频 | 亚洲精品性爱 | 亚洲中文字幕观看 |