JavaScript >> Javascript 文檔 >  >> JavaScript

10 分鐘了解 JavaScript Async/Await

在很長一段時間內,JavaScript 開發人員不得不依賴回調來處理異步代碼。結果,我們中的許多人都經歷過回調地獄,並且在面對看起來像這樣的函數時會感到恐懼。

謝天謝地,那麼(或者我們應該說 .then() ) 來了 Promise。它們為回調提供了一種更有條理的替代方案,並且大多數社區很快轉而使用它們。

現在,隨著最近添加的 Async/Await,編寫 JavaScript 代碼將變得更好!

什麼是異步/等待?

Async/Await 是一個期待已久的 JavaScript 特性,它使使用異步函數變得更加愉快和容易理解。它建立在 Promise 之上,兼容所有現有的基於 Promise 的 API。

名字來源於asyncawait - 幫助我們清理異步代碼的兩個關鍵字:

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

  • 自動將常規函數轉換為 Promise。
  • 當調用異步函數時,它們會解析其主體中返回的任何內容。
  • 異步函數允許使用 await .

Await - 暫停異步函數的執行。 (var result = await someAsyncCall(); )。

  • 當放置在 Promise 調用前面時,await 強制其餘代碼等到 Promise 完成並返回結果。
  • Await 僅適用於 Promises,不適用於回調。
  • Await 只能在 async 內部使用 功能。

這是一個簡單的例子,希望能把事情弄清楚:

假設我們想從我們的服務器獲取一些 JSON 文件。我們將編寫一個使用 axios 庫並向 https://tutorialzine.com/misc/files/example.json 發送 HTTP GET 請求的函數。我們要等待服務器響應,所以這個HTTP請求自然是異步的。

下面我們可以看到相同的功能實現了兩次。第一次使用 Promises,然後第二次使用 Async/Await。

// Promise approach

function getJSON(){

    // To make the function blocking we manually create a Promise.
    return new Promise( function(resolve) {
        axios.get('https://tutorialzine.com/misc/files/example.json')
            .then( function(json) {

                // The data from the request is available in a .then block
                // We return the result using resolve.
                resolve(json);
            });
    });

}

// Async/Await approach

// The async keyword will automatically create a new Promise and return it.
async function getJSONAsync(){

    // The await keyword saves us from having to write a .then() block.
    let json = await axios.get('https://tutorialzine.com/misc/files/example.json');

    // The result of the GET request is available in the json variable.
    // We return it just like in a regular synchronous function.
    return json;
}

很明顯,Async/Await 版本的代碼更短且更易於閱讀。除了使用的語法之外,這兩個函數完全相同——它們都返回 Promises 並使用來自 axios 的 JSON 響應進行解析。我們可以這樣調用我們的異步函數:

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

那麼,Async/Await 是否會使 Promise 過時?

一點都不。在使用 Async/Await 時,我們仍在底層使用 Promises。從長遠來看,對 Promises 的良好理解實際上會對您有所幫助,並且強烈推薦。

甚至在某些用例中 Async/Await 無法解決問題,我們必須返回 Promises 尋求幫助。一種這樣的場景是當我們需要進行多個獨立的異步調用並等待它們全部完成時。

如果我們嘗試使用 async 和 await 來執行此操作,將會發生以下情況:

async function getABC() {
  let A = await getValueA(); // getValueA takes 2 second to finish
  let B = await getValueB(); // getValueB takes 4 second to finish
  let C = await getValueC(); // getValueC takes 3 second to finish

  return A*B*C;
}

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

這不是最佳解決方案,因為三個變量 A , B , 和 C 不相互依賴。換句話說,我們不需要知道 A 的值 在我們得到 B 之前 .我們可以同時獲取它們,並減少幾秒鐘的等待時間。

同時發送所有請求 Promise.all() 是必須的。這將確保我們在繼續之前仍然擁有所有結果,但異步調用將並行觸發,而不是一個接一個。

async function getABC() {
  // Promise.all() allows us to send all requests at the same time. 
  let results = await Promise.all([ getValueA, getValueB, getValueC ]); 

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

這樣,該功能將花費更少的時間。 getValueAgetValueC 調用將在 getValueB 時完成 結束。我們將有效地減少執行到最慢請求的時間(getValueB - 4 秒),而不是時間的總和。

在 Async/Await 中處理錯誤

Async/Await 的另一個優點是它允許我們在一個好的舊 try/catch 塊中捕獲任何意外錯誤。我們只需要包裝我們的 await 像這樣調用:

async function doSomethingAsync(){
    try {
        // This async call may fail.
        let result = await someAsyncCall();
    }
    catch(error) {
        // If it does we will catch the error here.
    }  
}

catch 子句將處理由等待的異步調用或我們可能在 try 塊中編寫的任何其他失敗代碼引發的錯誤。

如果情況需要,我們還可以在執行異步函數時捕獲錯誤。由於所有異步函數都返回 Promises,我們可以簡單地包含一個 .catch() 調用它們時的事件處理程序。

// Async function without a try/catch block.
async function doSomethingAsync(){
    // This async call may fail.
    let result = await someAsyncCall();
    return result;  
}

// We catch the error upon calling the function.
doSomethingAsync().
    .then(successHandler)
    .catch(errorHandler);

選擇您喜歡的錯誤處理方法並堅持下去很重要。同時使用 try/catch 和 .catch() 很可能會導致問題。

瀏覽器支持

Async/Await 已經在大多數主流瀏覽器中可用。這僅不包括 IE11 - 所有其他供應商都將識別您的 async/await 代碼,而無需外部庫。

只要 Node 8 或更高版本的 Node 開發人員也可以享受改進的異步流程。它應該在今年晚些時候成為 LTS。

如果這種兼容性不滿足你,還有幾個 JS 轉譯器,比如 Babel 和 TypeScript,以及 Node.js 庫 asyncawait,它們提供了他們自己的跨平台版本的功能。

結論

隨著 Async/Await 的加入,JavaScript 語言在代碼可讀性和易用性方面取得了巨大飛躍。編寫類似於常規同步函數的異步代碼的能力將受到 JavaScript 初學者和資深程序員的讚賞。

  • MDN 上的異步
  • 在 MDN 上等待
  • Async/Await:當之無愧的 JavaScript 英雄
  • Async/Await 從何而來以及為什麼要使用它?

Tutorial JavaScript 教程
  1. VSCode 生產力:Magit 插件

  2. JavaScript-30-Day-9

  3. 通過不使用兩個 for 循環來循環對象

  4. 你使用 jQuery.html() 錯了!

  5. 將 Tailwind 與 Next.js 一起使用

  6. 網頁抓取 Javascript 元素,最好不使用 Selenium

  7. 如何從 Windows 7 升級到 Linux

  1. 在 Internet Explorer 和 Safari 中調試 JavaScript

  2. HTML 優先,JavaScript 最後:網絡速度的秘訣!

  3. SXSW:JavaScript 庫的秘密

  4. 如何在不包括小時的情況下比較日期

  5. 使用 Next.js 10 探索新的圖像組件

  6. NASA 任務控制 Deno 項目

  7. 發出 Axios 請求的實用函數

  1. Page Speed Insights (Lighthouse) 於 2021 年 6 月 1 日進行了升級 - 發生了哪些變化,它將如何影響您?

  2. |Yelp營|錯誤和驗證數據

  3. 使用 node.js 輕鬆創建 RESTful API |第1部分

  4. 在 Visual Studio 2017 中使用 npm、webpack 和 TypeScript 設置 ASP.NET Core:第二部分