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

          消滅異步回調(diào),還得是 async-await

          共 11095字,需瀏覽 23分鐘

           ·

          2022-08-03 01:22

          本篇,帶你讀懂a(chǎn)sync~await間的浪漫。

          關(guān)于異步處理問(wèn)題,ES5的回調(diào)讓我們陷入回調(diào)地獄輪回,后來(lái)ES6的Promise(Promise不了解?點(diǎn)這了解[1])讓我們脫離輪回,終于,ES7的async-await帶我們走向光明。今天我們就來(lái)學(xué)習(xí)一夏 async-await,看看與Promise有何聯(lián)系和區(qū)別。

          一、走進(jìn)Async-await原理
          1、原理1

          async函數(shù)返回一個(gè) Promise 對(duì)象,可以使用then方法添加回調(diào)函數(shù)。舉例說(shuō)明:

          // async返回的是Promise對(duì)象?
          async function testAsync() {
              return 'hello';//上篇文章Promise對(duì)象的返回值如果不是Promise,會(huì)通過(guò)Promise.resolve()轉(zhuǎn)化為Promise,再進(jìn)行處理
          }
          const result = testAsync()
          console.log(result);//Promise { 'hello' }  說(shuō)明async返回的是Promise對(duì)象
          復(fù)制代碼

          那既然async返回的是Promise對(duì)象,那么async后面的函數(shù)可以接.then()或者.catch()...嘛?我們?cè)囈辉嚲椭懒恕?/p>

          // async返回的是Promise對(duì)象,并且可以接Promise的方法?
          async function testAsync() {
              // await await等待還是promise對(duì)象
              return 'hello'
          }
          testAsync()
              .then((result)=>{
                  console.log(result);
              })
              .catch((error)=>{
                  console.log(error);
              })
          //hello  媽耶!打印了!說(shuō)明async返回的是Promise對(duì)象,并且可以接Promise的方法,并且!!!默認(rèn)狀態(tài)是resolved的
          復(fù)制代碼

          上面代碼說(shuō)明,async函數(shù)內(nèi)部return語(yǔ)句返回的值,會(huì)成為then方法回調(diào)函數(shù)的參數(shù)

          2、原理2

          當(dāng)async函數(shù)內(nèi)部拋出錯(cuò)誤的時(shí)候,會(huì)導(dǎo)致返回的 Promise 對(duì)象變?yōu)閞eject狀態(tài)。拋出的錯(cuò)誤對(duì)象會(huì)被.then()方法的第二個(gè)回調(diào)函數(shù)接收或者.catch()方法回調(diào)函數(shù)接收到。

          // async函數(shù)內(nèi)部拋出錯(cuò)誤或者Promise狀態(tài)為reject
          async function testError(){
             //throw new Error('出錯(cuò)啦~~');
             await Promise.reject('出錯(cuò)了');//await前面有return和沒(méi)有return效果一樣
          }
          testError()
             // .then(()=>{},(error)=>{console.log(error);})
            .catch(error=>{console.log(error);})
          //Error: 出錯(cuò)啦~~
          復(fù)制代碼
          3、原理3

          await命令后面是一個(gè) Promise 對(duì)象,返回該對(duì)象的結(jié)果。如果不是 Promise 對(duì)象,就直接返回對(duì)應(yīng)的值。代碼說(shuō)明:

          // await
          async function getName(){
              // return '來(lái)自星星的你';
              return await '來(lái)自星星的你';//上面直接return等價(jià)于這個(gè)return
          }
          getName()
              .then(result=>{console.log(result);})
          //來(lái)自星星的你
          復(fù)制代碼
          4、原理4

          await的使用,必須要有async。這便是async-await的浪漫所在了:async返回的是一個(gè)Promise對(duì)象,await等待的就是這個(gè)Promise對(duì)象,所以await不能沒(méi)有async(但是async可以沒(méi)有await)。有沒(méi)有被浪漫到?反正我是醉了。如果await沒(méi)有async會(huì)怎么樣?報(bào)錯(cuò):

          // await沒(méi)有async會(huì)報(bào)錯(cuò)
          function testAwait(){
             return await '西紅柿炒辣椒'
          }
          testAwait()
            .catch(error=>{
                 console.log(error);
            })
          //SyntaxError: await is only valid in async function
          復(fù)制代碼
          二、深入Async-await規(guī)則
          1、async封裝Promise
          // async封裝Promise
          async function fn1() {
              return '喜羊羊與灰太狼';// //相當(dāng)于return Promise.resolve('喜羊羊與灰太狼')
              const data = await fn1();//接收data值
          }
          fn1()//執(zhí)行async函數(shù),返回的是一個(gè)Promise對(duì)象
              .then(data => {
                  console.log('content =', data)
              })

          //content = 喜羊羊與灰太狼
          復(fù)制代碼
          2、await相當(dāng)于then
          // await---.then()
          async function getName(){
              const operate=Promise.resolve('白雪公主')//執(zhí)行函數(shù)
              const name= await operate //await相當(dāng)于Promise的then  operate.then(name=>{})
              console.log('name:',name)
          }
          getName();
          async function(){
              const person=await '七個(gè)小矮人' //await Promise.resolve('七個(gè)小矮人') await后面不跟Promise,也會(huì)被封裝成Promise
              console.log('person:',person)//400
          })();//自執(zhí)行函數(shù)

          //name: 白雪公主
          //person: 七個(gè)小矮人
          復(fù)制代碼
          3、多個(gè)await時(shí),按時(shí)序執(zhí)行

          當(dāng)函數(shù)執(zhí)行的時(shí)候,一旦遇到await就會(huì)先返回,等到異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語(yǔ)句。任何一個(gè)await語(yǔ)句后面的 Promise 對(duì)象變?yōu)閞eject狀態(tài),那么整個(gè)async函數(shù)都會(huì)中斷執(zhí)行

          async function testOrder() {
              await Promise.reject('出錯(cuò)了')//UnhandledPromiseRejectionWarning: 出錯(cuò)了
              await Promise.resolve('hello world'); // 不會(huì)執(zhí)行
          }
          testOrder();
          復(fù)制代碼
          4、try…catch相當(dāng)于catch

          如果希望即使前一個(gè)異步操作失敗,也不要中斷后面的異步操作。可將第一個(gè)await放在try...catch結(jié)構(gòu)里面,這樣不管這個(gè)異步操作是否成功,第二個(gè)await都會(huì)執(zhí)行。

          // try...catch
          !(async function () {
              const testError = Promise.reject('出錯(cuò)啦~~~')//rejected狀態(tài)
              // const testError=throw new Error('出錯(cuò)啦~~~');
              try {
                  const result = await testError; //await相當(dāng)于then,但是reject不會(huì)觸發(fā)then
                  console.log('success:'+result) //不會(huì)輸出,因?yàn)閏onst result = await testError被報(bào)錯(cuò),被catch捕獲
              } catch (error) {
                  console.error('error:'+error)//try...catch 相當(dāng)于Promise的catch
              }

          })()
          //error:出錯(cuò)啦~~~
          復(fù)制代碼

          當(dāng)await后面是Promise對(duì)象的時(shí)候,我們也可直接在await后面直接.catch捕獲錯(cuò)誤:

          async function testError() {
              await Promise.reject('出錯(cuò)了')
                  .catch(error => console.log(error));//這里捕獲錯(cuò)誤,不會(huì)影響下一個(gè)await執(zhí)行
              
              return await Promise.resolve('hello world');
          }

          testError()
              .then(result => console.log(result))
          復(fù)制代碼
          三、解析Async-await語(yǔ)法

          我們淺淺看一個(gè)面試題:

          // 面試題
          function getJSON() {
             return new Promise((resolve, reject) => {
                 setTimeout(() => {
                     console.log(2);
                     resolve(2)
                }, 2000)
            })
          }
          async function testAsync() {
             await getJSON()
             console.log(3);
          }
          testAsync()
          //2
          //3
          復(fù)制代碼

          問(wèn)題當(dāng)然不會(huì)問(wèn)打印順序啦,問(wèn)題是將async await語(yǔ)句解析翻譯為Promise?

          根據(jù)現(xiàn)在的知識(shí)面,我們必須知道:

          (1)await不能單獨(dú)出現(xiàn),其函數(shù)前面一定要有async。

          (2)await會(huì)干兩件事:

          第一,將寫在await后面的代碼放到async創(chuàng)建的那個(gè)Promise里面執(zhí)行。

          第二、將寫在await下面的代碼放到前一個(gè)創(chuàng)建的那個(gè)Promise對(duì)象的.then里面執(zhí)行。

          (3)await返回的也是Promise對(duì)象,他只是把a(bǔ)wait下面的代碼放到了await返回的promise的.then里面執(zhí)行。

          這樣的話,是不是如魚得水了。翻譯如下:

          function getJSON() {
             return new Promise((resolve, reject) => {
                 setTimeout(() => {
                     console.log(2);
                     resolve(2)
                }, 2000)
            })
          }
          // 編譯成Promise原理
          function testAsync() {
             return Promise.resolve().then(() => {
                 return getJSON();
            })
                .then(() => {
                     console.log(3);

                })
          }
          testAsync()
          復(fù)制代碼
          四、拓展Async-await應(yīng)用
          1、場(chǎng)景1

          你學(xué)廢async-await了嘛?還記得上一篇開篇的回調(diào)地獄嘛?我們通過(guò)Promise解決回調(diào)是這樣的:

          // Promise解決方式
          function doCallback(n{
              var myPromise = new Promise(function (resolve, reject{   
                  //處理異步任務(wù)
                  var flag = true;
                  setTimeout(function () {
                      if (flag) {
                          resolve(n)
                      }
                      else {
                          reject('失敗')
                      }
                  },0)
              })
              return myPromise;
          }

          doCallback(1)
              .then((result) => { //then是成功執(zhí)行的方法 返回的還是一個(gè)Promise對(duì)象
                  console.log(result);//打印張三  res是執(zhí)行
                  return fn(2);
              })
              .then((result) => {
                  console.log(result);
                  return fn(3)
              })
              .then((result) => {
                  console.log(result);
                  return fn(4)
              })
              .then((result) => {
                  console.log(result);
              })
              .catch((result) => { //catch是失敗執(zhí)行的方法
                  console.log(result);
              })
              //好多.then,形成.then鏈啦
          //1
          //2
          //3
          //4
          復(fù)制代碼

          通過(guò)以上Promise方法,可以明顯解決回調(diào)地獄“向右移”的浮夸表現(xiàn),但是,Promise是基于 then, catch 的鏈?zhǔn)秸{(diào)用,但也是基于回調(diào)函數(shù)。.then鏈多多少少還是違背原生代碼,顯得也不是很優(yōu)雅。作為回調(diào)終極武器,async-await更加貼近于原生代碼,我們看一下吧:

          //封裝一個(gè)返回promise的異步任務(wù)
          function doCallback(str{
              var myPromise = new Promise(function (resolve, reject{
                  var flag = true;
                  setTimeout(function () {
                      if (flag) {
                          resolve(str)
                      } else {
                          reject('處理失敗')
                      }
                  })
              })
              return myPromise;
          }

          //封裝一個(gè)執(zhí)行上述異步任務(wù)的async函數(shù)
          async function testAsync() {
              var result1 = await doCallback(1);  //await直接拿到fn()返回的promise的數(shù)據(jù),并且賦值給result
              var result2 = await doCallback(2);  //await 后面的代碼,都可以看做是異步回調(diào) callback 里的內(nèi)容,都是異步的
              var result3 = await doCallback(3);
              var result4 = await doCallback(4);
              console.log(result1);
              console.log(result2);
              console.log(result3);
              console.log(result4);
          }//這樣是不是簡(jiǎn)潔優(yōu)雅多了呢?
          //執(zhí)行函數(shù)
          testAsync();
          //1
          //2
          //3
          //4
          復(fù)制代碼

          有了 async-await、promise 還有必要學(xué)習(xí)嗎?通過(guò)上面async-await的解決方案可以瞧見(jiàn),async / await 和 Promise 并不互斥,二者相輔相成。同時(shí)async / await 并不能改變異步的本質(zhì)( js是單線程的,異步需要回調(diào),都是要基于 event loop 來(lái)實(shí)現(xiàn)(什么是event loop?關(guān)注我,等我文章~))。

          總結(jié)

          現(xiàn)在知道了,async-await是promise的語(yǔ)法糖了吧,不僅讓我們書寫代碼時(shí)更加流暢,而且增強(qiáng)了代碼的可讀性。特別注意的是:雖然async-await 是建立在 Promise機(jī)制之上的,但是并不能取代其地位,他們兩者相輔相成,息息相關(guān)。其實(shí)async-await不止是Promise的語(yǔ)法糖,還是Generator的語(yǔ)法糖,Generator是什么?我們下篇見(jiàn)分曉。

          heiehi.webp

          關(guān)于本文

          作者:來(lái)碗鹽焗星球

          https://juejin.cn/post/7122478595787718663


          最后


          歡迎關(guān)注【前端瓶子君】??ヽ(°▽°)ノ?
          回復(fù)「算法」,加入前端編程源碼算法群,每日一道面試題(工作日),第二天瓶子君都會(huì)很認(rèn)真的解答喲!
          回復(fù)「交流」,吹吹水、聊聊技術(shù)、吐吐槽!
          回復(fù)「閱讀」,每日刷刷高質(zhì)量好文!
          如果這篇文章對(duì)你有幫助,在看」是最大的支持
           》》面試官也在看的算法資料《《
          “在看和轉(zhuǎn)發(fā)”就是最大的支持

          瀏覽 34
          點(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>
                  日本 波多野结衣 影片 | 亚洲网站在线免费观看 | 在线日韩黄色 | 河南首富 越来越富 | 亚洲免费在线看黄 |