<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>

          明明有了 promise ,為啥還需要 async await ?

          共 8712字,需瀏覽 18分鐘

           ·

          2021-06-24 08:14

          推薦關(guān)注↓

          點(diǎn)擊上方 程序員成長(zhǎng)指北,關(guān)注公眾號(hào)

          回復(fù)1,加入高級(jí)Node交流群


          為了讓還沒(méi)聽(tīng)說(shuō)過(guò)這個(gè)特性的小伙伴們有一個(gè)大致了解,以下是一些關(guān)于該特性的簡(jiǎn)要介紹:

          async/await是一種編寫(xiě)異步代碼的新方法。在這之前編寫(xiě)異步代碼使用的是回調(diào)函數(shù)和promise。
          async/await實(shí)際是建立在promise之上的。因此你不能把它和回調(diào)函數(shù)搭配使用。
          async/await可以使異步代碼在形式上更接近于同步代碼。這就是它最大的價(jià)值。

          語(yǔ)法

          假設(shè)有一個(gè)getJSON方法,它返回一個(gè)promise,該promise會(huì)被resolve為一個(gè)JSON對(duì)象。我們想要調(diào)用該方法,輸出得到的JSON對(duì)象,最后返回"done"。

          以下是使用promise的實(shí)現(xiàn)方式:

          const makeRequest = () =>
            getJSON()
              .then(data => {
                console.log(data)
                return "done"
              })
          makeRequest()

          使用async/await則是這樣的:

          const makeRequest = async () => {
            console.log(await getJSON())
            return "done"
          }

          makeRequest()

          使用async/await時(shí)有以下幾個(gè)區(qū)別:

          在定義函數(shù)時(shí)我們使用了async關(guān)鍵字。await關(guān)鍵字只能在使用async定義的函數(shù)的內(nèi)部使用。所有async函數(shù)都會(huì)返回一個(gè)promise,該promise最終resolve的值就是你在函數(shù)中return的內(nèi)容。
          由于第一點(diǎn)中的原因,你不能在頂級(jí)作用域中await一個(gè)函數(shù)。因?yàn)轫敿?jí)作用域不是一個(gè)async方法。

          // this will not work in top level
          // await makeRequest()
              
          // this will work
          makeRequest().then((result) => {
            // do something
          })

          await getJSON()意味著直到getJSON()返回的promise在resolve之后,console.log才會(huì)執(zhí)行并輸出resolove的值。

          為何使用async/await編寫(xiě)出來(lái)的代碼更好呢?

          1. 簡(jiǎn)潔

          看看我們節(jié)省了多少代碼吧。即使是在這么一個(gè)簡(jiǎn)單的例子中,我們也節(jié)省了可觀的代碼。我們不需要為.then編寫(xiě)一個(gè)匿名函數(shù)來(lái)處理返回結(jié)果,也不需要?jiǎng)?chuàng)建一個(gè)data變量來(lái)保存我們實(shí)際用不到的值。我們還避免了代碼嵌套。這些小優(yōu)點(diǎn)會(huì)在真實(shí)項(xiàng)目中變得更加明顯。

          2. 錯(cuò)誤處理

          async/await終于使得用同一種構(gòu)造(古老而好用的try/catch) 處理同步和異步錯(cuò)誤成為可能。在下面這段使用promise的代碼中,try/catch不能捕獲JSON.parse拋出的異常,因?yàn)樵摬僮魇窃趐romise中進(jìn)行的。要處理JSON.parse拋出的異常,你需要在promise上調(diào)用.catch并重復(fù)一遍異常處理的邏輯。通常在生產(chǎn)環(huán)境中異常處理邏輯都遠(yuǎn)比console.log要復(fù)雜,因此這會(huì)導(dǎo)致大量的冗余代碼。

          const makeRequest = () => {
              try {
              getJSON()
                .then(result => {
                  // this parse may fail
                  const data = JSON.parse(result)
                  console.log(data)
                })
                // uncomment this block to handle asynchronous errors
                // .catch((err) => {
                //   console.log(err)
                // })
              } catch (err) {
                  console.log(err)
              }
          }

          現(xiàn)在看看使用了async/await的情況,catch代碼塊現(xiàn)在可以捕獲JSON.parse拋出的異常了:

          const makeRequest = async () => {
            try {
              // this parse may fail
              const data = JSON.parse(await getJSON())
              console.log(data)
            } catch (err) {
              console.log(err)
            }
          }

          3. 條件分支

          假設(shè)有如下邏輯的代碼。請(qǐng)求數(shù)據(jù),然后根據(jù)返回?cái)?shù)據(jù)中的某些內(nèi)容決定是直接返回這些數(shù)據(jù)還是繼續(xù)請(qǐng)求更多數(shù)據(jù):

          const makeRequest = () => {
            return getJSON()
              .then(data => {
                if (data.needsAnotherRequest) {
                  return makeAnotherRequest(data)
                    .then(moreData => {
                      console.log(moreData)
                      return moreData
                    })
                } else {
                  console.log(data)
                  return data
                }
              })
          }

          只是閱讀這些代碼已經(jīng)夠讓你頭疼的了。一不小心你就會(huì)迷失在這些嵌套(6層),空格,返回語(yǔ)句中。(當(dāng)然我們一般用請(qǐng)求數(shù)據(jù)的返回值作為判斷條件不會(huì)寫(xiě)成這樣,也許我這個(gè)小白會(huì)...) 在使用async/await改寫(xiě)后,這段代碼的可讀性大大提高了:

          const makeRequest = async () => {
            const data = await getJSON()
            if (data.needsAnotherRequest) {
              const moreData = await makeAnotherRequest(data);
              console.log(moreData)
              return moreData
            } else {
              console.log(data)
              return data    
            }
          }

          4. 中間值

          比如你向一個(gè)url1發(fā)送請(qǐng)求,拿到返回值1,然后用這個(gè)返回值1當(dāng)作參數(shù)去請(qǐng)求url2,拿到返回值2,然后拿返回值1和返回值2作為參數(shù)去請(qǐng)求url3,拿到最終的返回結(jié)果。
          對(duì)應(yīng)的代碼看起來(lái)是這樣的:

          const makeRequest = () => {
            return promise1()
              .then(value1 => {
                // do something
                return promise2(value1)
                  .then(value2 => {
                    // do something          
                    return promise3(value1, value2)
                  })
              })
          }

          如果promise3沒(méi)有用到value1,那么我們就可以把這幾個(gè)promise改成嵌套的模式。如果你不喜歡這種編碼方式,你也可以把value1和value2封裝在一個(gè)Promsie.all調(diào)用中以避免深層次的嵌套:

          const makeRequest = () => {
            return promise1()
              .then(value1 => {
                // do something
                return Promise.all([value1, promise2(value1)])
              })
              .then(([value1, value2]) => {
                // do something          
                return promise3(value1, value2)
              })
          }

          這種方式為了保證可讀性而犧牲了語(yǔ)義。除了避免嵌套的promise,沒(méi)有其它理由要把value1和value2放到一個(gè)數(shù)組里。

          同樣的邏輯如果換用async/await編寫(xiě)就會(huì)非常簡(jiǎn)單,直觀。

          const makeRequest = async () => {
            const value1 = await promise1()
            const value2 = await promise2(value1)
            return promise3(value1, value2)
          }

          5. 異常堆棧

          假設(shè)有一段串行調(diào)用多個(gè)promise的代碼,在promise串中的某一點(diǎn)拋出了異常:

          const makeRequest = () => {
            return callAPromise()
              .then(() => callAPromise())
              .then(() => callAPromise())
              .then(() => callAPromise())
              .then(() => callAPromise())
              .then(() => {
                throw new Error("oops");
              })
          }

          makeRequest()
            .catch(err => {
              console.log(err);
              // output
              // Error: oops at callAPromise.then.then.then.then.then (index.js:8:13)
            })

          從promise串返回的異常堆棧中沒(méi)有包含關(guān)于異常是從哪一個(gè)環(huán)節(jié)拋出的信息。更糟糕的是,它還會(huì)誤導(dǎo)你,它包含的唯一的函數(shù)名是callAPromise,然而該函數(shù)與此異常并無(wú)關(guān)系。(這種情況下文件名和行號(hào)還是有參考價(jià)值的)。

          然而,在使用了async/await的代碼中,異常堆棧指向了正確的函數(shù):

          const makeRequest = async () => {
            await callAPromise()
            await callAPromise()
            await callAPromise()
            await callAPromise()
            await callAPromise()
            throw new Error("oops");
          }

          makeRequest()
            .catch(err => {
              console.log(err);
              // output
              // Error: oops at makeRequest (index.js:7:9)
            })

          這帶來(lái)的好處在本地開(kāi)發(fā)環(huán)境中可能并不明顯,但當(dāng)你想要在生產(chǎn)環(huán)境的服務(wù)器上獲取有意義的異常信息時(shí),這會(huì)非常有用。在這種情況下,知道異常來(lái)自makeRequest而不是一連串的then調(diào)用會(huì)有意義的多。

          6. 調(diào)試

          最后壓軸的一點(diǎn),使用async/await最大的優(yōu)勢(shì)在于它很容易被調(diào)試。由于以下兩個(gè)原因,調(diào)試promise一直以來(lái)都是很痛苦的。

          你不能在一個(gè)返回表達(dá)式的箭頭函數(shù)中設(shè)置斷點(diǎn)(因?yàn)闆](méi)有代碼塊)


          如果你在一個(gè).then代碼塊中使用調(diào)試器的步進(jìn)(step-over)功能,調(diào)試器并不會(huì)進(jìn)入后續(xù)的.then代碼塊,因?yàn)檎{(diào)試器只能跟蹤同步代碼的『每一步』。

          通過(guò)使用async/await,你不必再使用箭頭函數(shù)。你可以對(duì)await語(yǔ)句執(zhí)行步進(jìn)操作,就好像他們都是普通的同步調(diào)用一樣。


          結(jié)論 async/await是過(guò)去幾年中JavaScript引入的最具革命性的特性之一。它使你意識(shí)到promise在語(yǔ)法上的糟糕之處,并提供了一種簡(jiǎn)單,直接的替代方案。

          參考文章

          https://loveky.github.io/2017/04/09/translte-6-reasons-why-javascripts-async-await-blows-promises-away/


          轉(zhuǎn)自:Angus安格斯

          https://juejin.cn/post/6960855679208783903

          最后

          如果覺(jué)得這篇文章還不錯(cuò)
          點(diǎn)擊下面卡片關(guān)注我
          來(lái)個(gè)【分享、點(diǎn)贊、在看】三連支持一下吧

             “分享、點(diǎn)贊在看” 支持一波 

          瀏覽 32
          點(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>
                  国产精品无码Al刘亦菲 | 草逼小视频| 亚洲春色校园 | 色777色 | 麻豆三级片大全 |