[譯]JavaScript: Promises 介紹及爲什麼 Async/Await 最終取得勝利

原文地址:JavaScript: Promises and Why Async/Await Wins the Battlejavascript

異步函數在JavaScript中有好有壞。好的一面是異步函數是非阻塞的,所以很快 - 特別是在Node.js上下文中。缺點是處理異步函數可能很麻煩,由於有時必須等待一個函數完成才能在進行下一次執行以前得到「回調」。java

有一些方法能夠發揮異步函數調用的優點並正確處理它們的執行,但其中一種方法遠遠優於其餘方法(Spoiler:它是Async / Await)。在本文中,您將瞭解使用PromisesAsync/Await的前因後果,以及咱們對二者之間如何比較的見解。數組

Promises vs. Callbacks

做爲JavaScript或Node.js開發人員,正確理解PromisesCallbacks之間的區別以及它們如何協同工做相當重要。promise

二者之間存在微小但重要的差別。在每一個Promise的核心,都有一個Callback解決某些數據(或錯誤),這些數據會被調用到Promise瀏覽器

回調處理程序: 異步

調用validatePassword()功能:
下面的代碼片斷顯示了驗證密碼的完整端到端檢查(它是靜態的,必須匹配「bambi」):
代碼註釋得很是好,可是,若是您感到困惑, catch只會在 reject()promise調用時執行。因爲密碼不匹配,咱們調用 reject(),所以 「catch」錯誤並將其發送到 done()函數。

Promises

與傳統的基於回調的方法相比,Promise爲執行、組合和管理異步操做提供了更簡單的替代方案。它們還容許你使用相似同步try / catch的方法處理異步錯誤。async

Promise還提供三種惟一的狀態函數

  1. Pending- promise的結果還沒有肯定,由於將產生其結果的異步操做還沒有完成。
  2. Fulfilled - 異步操做已完成,而且promise有值。
  3. Rejected - 異步操做失敗,promise永遠不會實現。在被拒絕狀態下,promise有一個reason能夠指示操做失敗的緣由。

promisepending狀態時,它能夠轉換爲fulfilledrejected的狀態。然而,一旦promise獲得fulfilledrejected,它將永遠不會過渡到任何其餘狀態,其value或失敗緣由不會改變。3d

缺點👎

Promise不作的一件事是解決所謂的「回調地獄」(原文:The one thing promises don’t do is solve what is called 「callback hell」, which is really just a series of nested function calls. ),「回調地獄」實際上只是一系列嵌套函數調用。固然,對於一個調用不要緊。可是對於多個調用,您的代碼將會難以閱讀和維護。code

在Promises中循環🎡

爲了不使用JavaScript進行深度嵌套回調,假設能夠簡單地遍歷Promises,將結果返回給對象或數組,並在完成後中止。不幸的是,這並不容易; 因爲JavaScript的異步特性,若是循環遍歷每一個Promise,在代碼完成時不會調用「done」事件。

處理這種狀況的正確方法是使用Promise.all()。這個函數在它被標記爲已完成以前等待全部的Fulfillments(或第一次rejection)。

錯誤處理💣

使用多個嵌套的Promise調用進行錯誤處理就像蒙着眼睛的駕駛汽車同樣。祝你好運找出哪一個Promise犯了錯誤。你最好的選擇是徹底刪除catch()方法並選擇加入全局錯誤處理程序,以下所示:

瀏覽器

Node.js
注意:以上兩個選項是確保捕獲錯誤的兩種方法。若是錯過了添加 catch()方法,它將被代碼吞噬。

Async/Await?🤔

Async/Await容許咱們編寫看起來是同步的異步JavaScript。在本文的前幾部分中,您瞭解了Promises - 它應該簡化異步流並避免回調地獄但它沒有。

回調地獄?🔥

Callback-hell是一個用於描述如下場景的術語:

注意:舉個例子,這是一個API調用,能夠從一個數組中得到4個特定用戶。

這樣的代碼這很難看,也佔用了大量的空間。Async/Await是JavaScript的最新和最好的東西,它容許咱們不只避免回調地獄,並且確保咱們的代碼乾淨而且錯誤被正確捕獲。我發現Async/Await最使人着迷的是它構建在Promises之上(非阻塞等),而且容許代碼可讀而且就像讀取它是同步的同樣。這就是關鍵所在。

注意:如下是一組API調用的示例,用於從一個數組中檢索4個用戶,超過一半的代碼行:

代碼這樣寫比較優雅,對嗎?💃

由於Async/Await是創建在Promises之上的,因此你甚至能夠在關鍵字await使用Promise.all()

注意:因爲同步特性, Async/await稍微慢一些。連續屢次使用它時應該當心,由於 await關鍵字會中止執行後面的全部代碼 - 就像在同步代碼中同樣。

如何開始使用Async/Await?💻

使用Async/Await很是容易理解和使用。實際上,它能夠在最新版本的Node.js中本地使用,而且正在迅速融入瀏覽器。如今,若是你想在客戶端使用它,你須要使用Babel。

異步Async

讓咱們從async關鍵字開始。它能夠放在function以前,以下所示:

等待Await

關鍵字await使JavaScript等待promise繼續並返回其結果。以下所示:

完整的例子

爲何Async/Await更好?😁

如今咱們已經瞭解了PromisesAsync/Await所提供的不少內容,讓咱們回顧一下爲何Stream認爲Async/Await是代碼庫的最佳選擇。

  1. Async/Await容許使用更少的代碼行,更少的輸入和更少的錯誤,提供簡潔明瞭的代碼庫。最終,它使複雜的嵌套代碼再次可讀。
  2. 使用try/catch處理錯誤(在一處,而不是在每一個調用中)
  3. 錯誤堆棧是有意義的,而不是從Promises收到的模糊錯誤,它們很大而且很難找到錯誤發生的位置。最重要的是,錯誤指向錯誤發生的函數。

最後的想法📃

能夠說Async/Await是過去幾年中添加到JavaScript中的最強大的功能之一。

花了不到一天的時間來理解語法,看看咱們的代碼庫在這方面是多麼糟糕。將咱們全部基於Promise的代碼轉換爲Async/Await總共花費了大約兩天時間,這其實是一個徹底重寫 - 這只是爲了說明使用Async/Await時須要更少的代碼。

相關文章
相關標籤/搜索