理解 es7 async await

Pandaaa發表於2018-06-26

說明

  • 開始進行 react 專案,需要用到 es7 的 async 和 await 來替代以前的 promise 的方法q請求介面。在這裡學習一下和大家一起分享。
  • 適用:es6,es7初學者

一 理解 promise

  • 需要明白 es7 的 await 和 async 是什麼我們想要看看 promise 是什麼?

promise 的使用

老式的處理方法

  • 在講 promise 之前我們也需要先了解一下,我們平時在處理介面成功和失敗的時候的處理方法如下。?
function successCallback(result) {
  console.log("It succeeded with " + result);
}

function failureCallback(error) {
  console.log("It failed with " + error);
}

doSomething(successCallback, failureCallback);
複製程式碼

promise替代了下面這種舊式的函式,這種舊式函式需要兩個回撥函式,並最終呼叫處理成功事件或者處理失敗事件的回撥函式

用 promise 處理非同步

  • 一個 Promise 就是一個代表了非同步操作最終完成或者失敗的物件,新式函式返回一個你可以直接繫結回撥函式的promise物件,來代替上面?那種舊式的函式形式如下?:
const promise = doSomething(); 
promise.then(successCallback, failureCallback);

// 當然你可以簡單一點
doSomeThing().then(successCallback,failureCallback)
複製程式碼

promise 鏈式呼叫

  • 如果我們有多個非同步操作,和需要在一個請求成功後再請求其他的介面。以前我們是這樣做的
doSomething(function(result) {
  doSomethingElse(result, function(newResult) {
    doThirdThing(newResult, function(finalResult) {
      console.log('Got the final result: ' + finalResult);
    }, failureCallback);
  }, failureCallback);
}, failureCallback);
複製程式碼

這就是我們熟知的回撥地獄

  • 一些常見的需求我們不得不連續進行兩個或者跟多的非同步操作和請求,每一個請求都需要在上個請求的成功的執行之後進行。我們可以通過 promise chain 來完成這種需求。
doSomething().then(function(result) {
  return doSomethingElse(result);
})
.then(function(newResult) {
  return doThirdThing(newResult);
})
.then(function(finalResult) {
  console.log('Got the final result: ' + finalResult);
})
.catch(failureCallback);
複製程式碼

避免了回撥地獄我們現在這樣處理


我們花了些時間瞭解 promise 做鋪墊,下面來了解 async 和await 的使用

二 async function

async 返回值

  • async用於定義一個非同步函式,該函式返回一個Promise。

await

  • await 操作符用於等待一個Promise 物件。它只能在非同步函式 async function 中使用。

概況

  • 在 es7 的 draft 中提出 async 和 await來進一步的解決非同步函式的問題。
  • async function 宣告將定義一個返回 AsyncFunction 物件的非同步函式。

你還可以使用 非同步函式表示式 來定義非同步函式。

  • demo
function resolveAfter2Seconds() {
  return new Promise(resolve => {
    setTimeout(() => {
      resolve('resolved');
    }, 2000);
  });
}

async function asyncCall() {
  console.log('calling');
  var result = await resolveAfter2Seconds();
  console.log(result);
  // expected output: "resolved"
}

asyncCall();
複製程式碼

詳解?的 demo

  • 當呼叫一個 async 函式時,會返回一個 Promise 物件。當這個 async 函式返回一個值時,Promiseresolve 方法會負責傳遞這個值;當 async 函式丟擲異常時,Promisereject 方法也會傳遞這個異常值。
  • async 函式中可能會有 await 表示式,這會使 async 函式暫停執行,等待表示式中的 Promise 解析完成後繼續執行 async 函式並返回解決結果。

async/await的用途是簡化使用 promises 非同步呼叫的操作,並對一組 Promises執行某些操作。正如Promises類似於結構化回撥,async/await類似於組合生成器和 promises。

用 async 改寫 promise

  • promise chain
function getProcessedData(url) {
  return downloadData(url) // returns a promise
    .catch(e => {
      return downloadFallbackData(url)  // returns a promise
        .then(v => {
          return processDataInWorker(v); // returns a promise
        }); 
    })
    .then(v => {
      return processDataInWorker(v); // returns a promise
    });
}
複製程式碼
  • async function
async function getProcessedData(url) {
  let v;
  try {
    v = await downloadData(url); 
  } catch (e) {
    v = await downloadFallbackData(url);
  }
  return processDataInWorker(v);
}
複製程式碼

注意,在上述示例中,return 語句中沒有 await 操作符,因為 async function 的返回值將隱式傳遞給 Promise.resolve。

寫法

  • 現在我們這樣的來書寫非同步請求
const signup = async () => {
            try {
                const resp = await signUp(parmas);
                doSometing(resp);
            } catch (error) {
                alert(error);
            }
        }
    };
複製程式碼

async 函式異常

  • 我們直接在async函式中丟擲一個異常,由於返回的是一個Promise,因此,這個異常可以呼叫返回Promise的catch()方法捕捉到。
let sayHi = async functionsayHi(){
    throw new Error('出錯了');
}
sayHi().then(result=> {
    console.log(result);
}).catch(err=> {
    console.log(err.message);   //出錯了
});
複製程式碼
  • 和Promise鏈的對比:

我們的async函式中可以包含多個非同步操作,其異常和Promise鏈有相同之處,如果有一個Promise被reject()那麼後面的將不會再進行。

引用

mdn promise&async function

相關文章