10分鐘解讀 JavaScript Async/Await

JavaScript

在很長一段時間裏,JavaScript 開發人員不得不依賴回調來處理異步代碼。所以,咱們中的許多人都經歷過回調地獄,當面對這樣的函數時,咱們會感到無賴javascript

不過好在JavaScript提供了,.then()的一種回覆方式,目前也有不少人正在用他java

如今,隨着 Async/Await 的最新增長,編寫 JavaScript 代碼將會變得更加優雅!ios

什麼是 Async/Await?

Async/Await 是一個期待已久的 JavaScript 特性,它使得使用異步函數變得更加愉快和更容易理解。它創建在 Promises 之上,並與全部現有的基於 promise 的 api 兼容json

這個名字來自 async 和 await ——這兩個關鍵詞能夠幫助咱們清理異步代碼:axios

Async-聲明一個異步函數(Async function someName (){ ... })api

  1. 自動地將一個普通的函數轉換成一個承諾
  2. 當調用異步函數時,當異步完成時,而後返回的是異步內容
  3. 在異步函數中容許使用await

Await-暫停 async 函數的執行數組

  1. 當被放置在一個Promise前時, 強制代碼的其他部分等待,直到承諾完成並返回結果
  2. 只對 Promises 起做用,對 callback 不起做用
  3. 只能在裏面使用async函數中使用

經過一個簡單的例子來分析

假設咱們想從服務器獲取一些 JSON 文件。咱們將編寫一個使用 axios 庫的函數,並向 https://tutorialzine.com/misc... 發送一個 HTTP GET 請求。咱們必須等待服務器響應,因此這個 HTTP 請求天然是異步的promise

下面咱們能夠看到同一個函數實現了兩個。首先是使用 Promises,而後是第二個使用 Async/Await服務器

// Promise
function getJSON(){
    // 爲了使函數阻塞,咱們手動建立一個承諾.
    return new Promise( function(resolve) {
        axios.get('https://tutorialzine.com/misc/files/example.json')
            .then( function(json) {
                // 在.then中得到返回的json數據
                // 咱們使用resolve返回結果
                resolve(json);
            });
    });

}

// Async/Await
// async關鍵字將自動建立一個新的Promise並返回它.
async function getJSONAsync(){

    // await關鍵字使咱們沒必要編寫then().
    let json = await axios.get('https://tutorialzine.com/misc/files/example.json');

    // GET請求的結果在json變量中可用.
    // 獲取數據就像在一個常規的同步函數中同樣
    return json;
}

很明顯,Async/Await 版本的代碼更短,更容易閱讀。除了使用的語法以外,這兩個函數徹底相同——它們都返回 Promises 並使用 axios 的 JSON 響應解析。咱們能夠這樣調用咱們的 async 函數:異步

async返回自己就是一個Promise

getJSONAsync().then( function(result) {
    // Do something with result.
});

Async/Await 會使承諾過期嗎?

不,一點也不。
在使用 Async/Await 時,咱們仍然在引擎蓋下使用 Promises。
從長遠來看,充分理解Promise實際上會對你有所幫助,所以強烈推薦你這麼作

甚至在一些狀況下 Async/Await 也不能解決問題,咱們不得不回到 Promises 尋求幫助。其中一種狀況是,咱們須要進行多個獨立的異步調用,並等待它們所有完成

若是咱們嘗試使用 async 和 await 來實現這個功能,將會發生如下狀況:

async function getABC() {
  let A = await getValueA(); // getValueA 須要2秒
  let B = await getValueB(); // getValueB 須要4秒
  let C = await getValueC(); // getValueC 須要3秒
  return A*B*C;
}

每一個await等待都將等待await前一個返回結果。由於咱們一次只調用一個函數,整個函數從開始到結束(2 + 4 + 3)須要9秒

這不是最佳解決方案,由於三個變量 a、 b 和 c 並不相互依賴。換句話說,在獲得 b 以前,咱們不須要知道 a 的值。咱們能夠在同一時間獲得它們,減小几秒鐘的等待時間

在同一時間發送全部請求。這將確保咱們在繼續以前仍然擁有全部的結果,可是異步調用將並行請求,而不是一個接一個地請求

async function getABC() {
  // Promise.all()容許咱們同時發送多個請求,類型是個數組

  let results = await Promise.all([ getValueA, getValueB, getValueC ]); 

  return results.reduce((total,value) => total * value);
}

這樣一來,函數運行的時間就會少得多。getValueA 和 getValueC 調用在 getValueB 結束時已經完成,將有效地將執行時間減小到最慢的請求的時間(getValueB-4秒) ,而不是總和

Async/Await 中的錯誤處理

Async/Await 的另外一個優勢是,它容許咱們在一個很好在 try/catch 塊中捕捉任何意外的錯誤。只須要像這樣包裝下Await:

async function doSomethingAsync(){
    try {
        // 這裏異步可能會發送失敗
        let result = await someAsyncCall();
    }
    catch(error) {
        // 若是失敗了,經過catch捕捉到錯誤
    }  
}

Catch 子句將處理等待的異步調用或者咱們在 try 塊中編寫的任何其餘失敗代碼所引起的錯誤

若是狀況須要,咱們還能夠在執行 async 函數時捕獲錯誤。由於全部的異步函數都返回 Promises,咱們能夠簡單地包含一個。在調用 catch ()事件處理程序時。

async function doSomethingAsync(){
    // This async call may fail.
    let result = await someAsyncCall();
    return result;  
}

// 後面更用catch捕獲錯誤
doSomethingAsync().
    .then(successHandler)
    .catch(errorHandler);

總結

隨着 Async/Await 的加入,JavaScript 語言在代碼可讀性和易用性方面取得了巨大的飛躍。編寫相似於常規同步函數的異步代碼的能力將受到初學者、 JavaScript 開發者和資深編碼者的青睞

文章屬於翻譯,做者:羊先生
英文原文

vipbic.png

相關文章
相關標籤/搜索