站長資訊網
        最全最豐富的資訊網站

        async屬于es6屬性嗎

        屬于,async是es6的新特性,用于表明程序里面可能有異步過程。用async關鍵字聲明的函數返回的是一個Promise對象,如果在函數中return一個直接量,async會把這個直接量通過Promise.resolve()封裝成Promise對象;當async函數沒有返回值時,返回“Promise.resolve(undefined)”。

        async屬于es6屬性嗎

        前端(vue)入門到精通課程:進入學習
        Apipost = Postman + Swagger + Mock + Jmeter 超好用的API調試工具:點擊使用

        本教程操作環境:windows7系統、ECMAScript 6版、Dell G3電腦。

        ES6新特性 async和await關鍵字

        1、初步了解

        我們先從字面意思來理解這兩個關鍵字,async是asynchronous(異步)的簡寫,而await可以認為是async wait的簡寫。所以async可以理解為用于聲明一個函數是異步的,而await用于等待一個異步任務執行完成。

        async和await關鍵字讓我們可以用一種更簡潔的方式寫出基于promise的異步行為,而無需刻意地鏈式調用promise。

        接下來我們通過先幾個例子,初步了解一下async和await的作用。

        知識點1: 用 async 關鍵字聲明的函數返回的是一個 Promise 對象。如果在函數中 return 一個直接量,async 會把這個直接量通過 Promise.resolve() 封裝成 Promise 對象。當 async 函數沒有返回值時,返回 Promise.resolve(undefined)

         //定義一個普通函數,返回一個字符串  function test() {      return "hello async";  }  const result1 = test();  console.log(result1); //輸出一個字符串 hello async    //定義一個使用了async修飾的函數,同樣返回一個字符串  async function testAsync() {      return "hello async";  }  const result2 = testAsync();  console.log(result2); //輸出一個Promise對象 Promise {<fulfilled>: 'hello async'}
        登錄后復制

         //async較好的用法  async function testAsync(){      //返回一個Promise對象      return new Promise((resolve, reject)=>{          //處理異步任務          setTimeout(function () {              resolve("testAsync")          }, 1000);      })  }  //async通常用于聲明一個處理異步任務且返回了Promise對象的函數
        登錄后復制

        知識點2: await關鍵字只能使用在被async聲明的函數內,用于修飾一個Promise對象,使得該Promise對象處理的異步任務在當前協程上按順序同步執行。

         //定義一個使用async修飾的函數,處理異步任務  async function testAsync(){      return new Promise((resolve, reject)=>{          setTimeout(function () {              resolve("testAsync")          }, 1000);      })  }
        登錄后復制

         //定義一個函數,直接調用testAsync函數  function testAwait(){      console.log('testAsync調用前')      testAsync().then(res=>{          console.log(res) //輸出"testAsync"      })      console.log('testAsync調用后')  }    /***** 輸出如下 *****/  testAsync調用前  testAsync調用后  testAsync  //盡管代碼按順序寫,但不按順序執行,因為testAsync()是異步函數
        登錄后復制

         //定義一個函數(不使用async聲明該函數)用await修飾調用testAsync函數  function testAwait(){      console.log('testAsync調用前')      await testAsync().then(res=>{ //使用await關鍵字修飾          console.log(res)      })      console.log('testAsync調用后')  }    //調用testAwait()函數  testAwait()  //報錯:Uncaught SyntaxError: await is only valid in async functions and the top level bodies of modules,因為await只能使用在被async修飾的函數內。
        登錄后復制

         //定義一個函數(使用async聲明該函數)用await修飾調用testAsync函數  async function testAwait(){      console.log('testAsync調用前')      await testAsync().then(res=>{          console.log(res)      })      console.log('testAsync調用后')  }    /***** 輸出如下 *****/  testAsync調用前  testAsync  testAsync調用后    //使用了await關鍵字修飾,使得代碼按照順序執行,即同步執行
        登錄后復制

        2、async關鍵字

        (1)用于表明程序里面可能有異步過程

        (2)async函數返回值的類型為Promise對象: 這是和普通函數本質上不同的地方,也是使用時重點注意的地方;

        • return newPromise( ),這個用法符合async函數本意;
        • return data,特別注意到是這樣子寫相當于Promise.resolve(data),返回的data被封裝成一個Promise對象,但是在調用async函數的地方通過簡單的=是拿不到這個返回值data的,因為返回值是一個Promise對象,所以需要用.then(data => { })方式才可以拿到這個data;
        • 如果沒有返回值,相當于返回了Promise.resolve(undefined);

        (3)無等待,非阻塞:使用async關鍵字聲明的函數里面如果有異步過程可能會等待,但是函數本身會馬上返回,不會阻塞當前主線程。如果在函數里面使用了await關鍵字修飾的異步過程,其工作在相應的協程上,會阻塞等待異步任務的完成再返回。

         //定義一個函數,處理異步任務(使用定時器模擬),返回一個Promise對象  async function testAsync(){      return new Promise((resolve, reject) => {        setTimeout(function () {          resolve("成功調用testAsync")        }, 1000);      });  }    //定義一個函數,使用await關鍵字修飾調用testAsync()函數  async function testAwait(){      //使用了await關鍵字修飾調用testAsyn()函數      await this.testAsync().then(res=>{        console.log(res) //輸出的是testAsync()函數resolve的值      });      console.log("helloAsync");  }    //主線程  console.log('testAwait調用前')  testAwait();  console.log('testAwait調用后')    /***** 輸出結果如下 *****/  testAwait調用前  testAwait調用后 //因為testAwait()函數使用了async關鍵字修飾,所以不會阻塞主線程的執行,所以這兩句話會先直接輸出,然后再執行testAwait()函數  成功調用testAsync //因為testAwait()函數在內部調用testAsync()函數時使用了await關鍵字修飾,所以在對應的協程上會阻塞,等待testAsync()函數執行完,再輸出下面那句'helloAsync'  helloAsync
        登錄后復制

        3、await關鍵字

        (1)await只能在async函數內部使用:不能放在普通函數里面,否則會報錯。

        (2)await關鍵字后面跟的是一個Promise對象。如果跟的是一個函數,則這個函數應當返回一個Promise對象。如果跟的是非Promise對象,則會通過Promise.resolve( )函數自動將這個東西包裝成一個Promise對象并置于fulfilled狀態。

         //例如:  const a = await 'Hello Await'  // 相當于  const a = await Promise.resolve('Hello Await');    console.log(a) //輸出 'Hello Await'
        登錄后復制

        (3)await的本質是等待它所修飾的Promise對象的fulfilled狀態,并把resolve(data)的數據data返回。

        意思是,如果await后面跟的是一個 Promise 對象,await 就會阻塞后面的代碼,等著 Promise 對象 resolve,然后得到 resolve 的值,作為 await 表達式的運算結果。

         async function testAsync(){      return new Promise((resolve, reject) => {        setTimeout(function () {          resolve("成功調用testAsync")        }, 1000);      });  }    const a = await testAsync() //這里的a就會拿到testAsync函數resolve的數據  console.log(a) //在一秒后輸出'成功調用testAsync'
        登錄后復制

        (4)await并不關心它所修飾的Promise對象的rejected狀態,即reject(data)的數據data并不會被await處理,所以建議通過Promise對象調用catch去捕獲。

         async testAwait(){      //變量a用于接收testAsync()函數resolve的數據      let a = await testAsync().catch(err=>{          //處理異常和reject的數據      })      }
        登錄后復制

        4、深入講解async和await

        (1)執行順序

         //定義一個函數,該函數接收一個參數,1s后再返回參數的兩倍  async function double(num) {      return new Promise((resolve, reject) => {          setTimeout(() => { //使用定時器模擬異步任務              resolve(2 * num) //將運算結果交給resolve          }, 1000);      })  }    async function getResult () {      console.log('double調用前')  //順序:2      let result = await double(10); //將10作為參數傳遞給double函數      //result變量用于接收double()函數resolve的值      console.log(result); //順序:4      console.log('double調用后') //順序:4  }    console.log('getResult調用前') //順序:1  getResult();  console.log('getResult調用后') //順序:3    /***** 依次輸出如下 *****/  getResult調用前  double調用前  getResult調用后  20 //1s后輸出  double調用后
        登錄后復制

        ①首先打印輸出getResult調用前,同步代碼,順序執行;

        ②然后調用方法getResult( ),打印輸出double調用前,同步代碼,順序執行;

        ③再調用異步方法double( )

        如果此處沒有使用await關鍵字修飾,則依次輸出的是:getResult調用前、double調用前、double調用后、getResult調用后、1s后輸出20

        因為異步操作不會影響其他代碼的執行,所以會將其他代碼按順序執行完,最后再執行double函數

        因為這里使用了await關鍵字,所以getResult( )的代碼執行到這里就會被阻塞,等到double函數resolve了,再往下執行

        ④盡管getResult函數內部被await阻塞了,由于getResult函數本身也是個async函數,所以它不會影響getResult函數外面的代碼執行。因為調用async函數不會造成阻塞,它內部的所有阻塞都被封裝在一個Promise對象中異步執行。

        ⑤所以在調用getResult函數后,會繼續向下執行,即打印輸出getResult調用后

        ⑥當1s之后,異步函數double執行完成,將結果交給resolve。

        ⑦通過await關鍵字接收到double函數resolve的值,賦值給result變量。打印輸出20

        ⑧因為使用了await阻塞將異步變為同步,所以在打印輸出20后再打印輸出double調用后

        (2)處理reject回調

         //方法一:通過promise對象的catch進行捕獲  function a(){      return new Promise((resolve,reject) => {          setTimeout(() => {              reject("something")          }, 1000)      })  }    async function b(){      let r = await a().catch((err)=>{          console.log(err)      })  }
        登錄后復制

         //方法二:通過try/catch語句處理  function a(){      return new Promise((resolve,reject) => {          setTimeout(() => {              reject("something")          }, 1000)      })  }    async function b(){      let r = null      try{         r = await a()      }catch(err){          console.log(err)      }  }
        登錄后復制

        (3)使用await優化Promise對象的回調地獄問題

        在Promise章節中我們通過了Promise對象的then( )方法鏈式調用解決了回調地獄問題,但看起來仍然不夠美觀,我們可以通過await優化一下,讓它看起來更符合我們平時代碼的編寫習慣。

         //原本的解決方案  //第二個請求依賴于第一個請求的返回值,第三個請求依賴于第二個請求的返回值  request1().then(function(data){       return request2(data)  }).then(function(data){       return request3(data)  })  //這里只發送了三次請求,代碼看起來還不錯,雖然它已經比普通的回調函數形式好了很多。  //那如果需要發送五次或十次請求呢?代碼也許會沒那么美觀,接下來我們使用學習到的await去解決這個問題。
        登錄后復制

        原本的要求是每個請求都依賴于上一個請求的返回值,那么是不是得等一個請求完,才能發送下一個請求?這時我們可以思考一下,await的作用是什么?是不是對一個Promise對象去進行阻塞,使其狀態變為fulfilled后獲取resolve的值。這不就正是我們所需要的。

         //使用await的解決方案  var res1 = await request1() //將request1的返回值賦值給res1  var res2 = await request2(res1) //將res1作為參數傳給request2,并將request2的返回值賦值給res2  var res3 = await request3(res2) //同理    //這樣子寫的代碼更加的美觀,并且更符合我們平時編寫代碼的習慣
        登錄后復制

        贊(0)
        分享到: 更多 (0)
        網站地圖   滬ICP備18035694號-2    滬公網安備31011702889846號
        主站蜘蛛池模板: 国产精品九九久久精品女同亚洲欧美日韩综合区 | 国产精品久久久久久影院| 精品久久久久国产免费| 精品久久久久久久久午夜福利| 久久人人超碰精品CAOPOREN| 91po国产在线精品免费观看| 99热精品在线观看| 国产欧美亚洲精品A| 一本之道av不卡精品| 久久精品国产精品亚洲人人| 国产999精品久久久久久| 国产办公室秘书无码精品99| 久久综合国产乱子伦精品免费| 亚洲精品成人片在线观看| 久久精品国产精品亜洲毛片| 国产精品久久久久乳精品爆| 国产精品福利在线播放| 国产精品扒开腿做爽爽爽视频| 亚洲国产另类久久久精品| 日韩一区二区三区在线精品| 国产在线91精品入口| 国产精品亚洲二区在线观看| 亚洲综合国产精品| 欧美精品黑人巨大在线播放| 久久国产精品-久久精品| 国产精品国产三级国产专播 | 奇米精品视频一区二区三区| 亚洲精品制服丝袜四区| 亚洲国产欧美日韩精品一区二区三区 | 自拍偷在线精品自拍偷无码专区 | 精品人妻无码专区中文字幕| 9久热这里只有精品| 久久精品嫩草影院| 国产精品你懂的| 久久国产免费观看精品| 国产精品亚洲专区在线观看 | 中文成人无码精品久久久不卡 | 亚洲精品成人片在线观看精品字幕| 婷婷久久精品国产| 亚洲欧美一级久久精品| 日韩精品欧美亚洲|