es6的async函數學習

async函數的使用方式,直接在普通函數前面加上async,表示這是一個異步函數,在要異步執行的語句前面加上await,表示後面的表達式須要等待。async是Generator的語法糖,相比較Generator函數在如下四方面作了改進es6

async相對於Generator的優勢

1.有內置執行器,不用調用next

Generator函數是須要調用next指令來運行異步的語句,async不須要調用next,直接像運行正常的函數那樣運行就能夠promise

2.有更好的語義化

語義化更明確,相比較於Generator的*和yield,async和await更明確。異步

3.await後面能夠跟promise或者任意類型的值

yield命令後面只能是 Thunk 函數或 Promise 對象,而async函數的await命令後面,能夠是Promise 對象和原始類型的值(數值、字符串和布爾值,但這時等同於同步操做)。async

4.返回一個promise對象,能夠調用.then

async直接返回一個promise對象,能夠用then和cache來處理。函數

async function getStockPriceByName(name) {
        let symbol = await getStockSymbol(name);
        let price = await getPriceByName(symbol);
        return price
    }
    getStockPriceByName('goog').then( (result)=> {
        console.log(result);
    }).catch((err)=>{
         console.log(err)
    })

上面的async異步函數遇到await會先返回一個Promise對象,等到異步操做執行完畢,纔會根據結果來執行具體的回調函數。spa

async 函數多種形式

    1. 函數聲明code

      async function foo() {}
    2. 表達式聲明對象

      var bar = async function () {}
    1. 對象聲明遞歸

      var obj = {
              async bazfunction(){
              }
          }
    2. 箭頭函數聲明字符串

      var fot = async() => {  }

    await 語句

    1. await後面是一個promise對象,若是不是,會轉成一個resolve的promise對象

    async function f() {
              return await 123;
          }
          f().then(function (a) {
              console.log(a);
          })
    1. await後面的promise對象,若是reject,則reject參數會被cache參數接收到,寫不寫return均可以,而且reject下面的代碼不會執行,若是想下面的代碼執行,必須用try cache包住

    async function a() {
               try{
                  await Promise.reject('出錯了!')
               }catch (e){
                  return await Promise.resolve('請從新填寫') 
               }
          }
          a().then(function () {
             console.log(err);
          }).catch(function (err) {
              console.log(err);
          })

    上面的代碼若是不用try cache包裹reject,則下面的代碼不會執行,而且reject語句是不用return返回的,resolve語句是須要用return返回;

    async錯誤處理經常使用寫法

    若是await後面的異步操做出錯,那麼等同於async函數返回的 Promise 對象被reject。因此一般的處理方法有兩種

    1. 用try catch包住可能會出錯的部分

    async function myFunction() {
              try {
                  await somethingThatReturnsAPromise();
              } catch (err) {
                  console.log(err);
              }
          }
    1. 另外一種寫法是對可能要出錯的異步操做添加catch回調函數

    async function myFunction() {
               await somethingThatReturnsAPromise().catch((err)=> {
                       console.log(err);
               })
           }

    多個await語句同時觸發

    let a=await getFoo();
      let b=await getBar();

    上面的兩個方法都是異步操做,不存在依賴關係,因此咱們能夠同時觸發,改寫成下面的

    //第一種寫法
      let [a,b]=Promise.all([getFoo(),getBar()])
      //第二種寫法
      let aPromise=getFoo();
      let bPromise=getBar();
      let a=await aPromise;
      let b=await bPromise;

    async 函數的實現原理

    async函數就是將執行器和Generator作爲一個函數返回。

    async function fn(){}
      //等同於
      function fn() {
        return spawn(function* () {
          
        })
      }
    function spawn(genF) {
              /****
               * 返回的是一個promise
               */
              return new Promise(function(resolve, reject) {
                  var gen=genF(); //運行Generator這個方法;
                  /***
                   * 執行下一步的方法
                   * @param fn 一個調用Generator方法的next方法
                   */
                 function step(fn) {
                      //若是有錯誤,則直接返回,不執行下面的await
                     try {
                      var next=fn();
                     }catch (e){
                       return reject(e)
                     }
                      //若是下面沒有yield語句,即Generator的done是true
                     if(next.done){
                        return resolve(next.value);
                     }
                     // 若是下面還有yield語句,resolve繼續執行遞歸執行gen.next(),reject則拋出錯誤
                     Promise.resolve(next.value).then((val)=>{
                         step(function(){ return gen.next(val) } )
                     }).catch((e)=>{
                         step(function(){ return gen.throw(e) } )
                     })
                 }
                  step(function () {
                     return gen.next();
                 })
              });
          }

    參考阮大神的文章:http://es6.ruanyifeng.com/#do...

    相關文章
    相關標籤/搜索