原文地址:JavaScript: Promises and Why Async/Await Wins the Battlejavascript
異步函數在JavaScript中有好有壞。好的一面是異步函數是非阻塞的,所以很快 - 特別是在Node.js上下文中。缺點是處理異步函數可能很麻煩,由於有時必須等待一個函數完成才能在進行下一次執行以前得到「回調」。java
有一些方法能夠發揮異步函數調用的優點並正確處理它們的執行,但其中一種方法遠遠優於其餘方法(Spoiler:它是Async / Await)。在本文中,您將瞭解使用Promises和Async/Await的前因後果,以及咱們對二者之間如何比較的見解。數組
做爲JavaScript或Node.js開發人員,正確理解Promises
和Callbacks
之間的區別以及它們如何協同工做相當重要。promise
二者之間存在微小但重要的差別。在每一個Promise
的核心,都有一個Callback
解決某些數據(或錯誤),這些數據會被調用到Promise
。瀏覽器
回調處理程序: 異步
catch
只會在
reject()
從
promise
調用時執行。因爲密碼不匹配,咱們調用
reject()
,所以
「catch」
錯誤並將其發送到
done()
函數。
與傳統的基於回調的方法相比,Promise
爲執行、組合和管理異步操做提供了更簡單的替代方案。它們還容許你使用相似同步try / catch
的方法處理異步錯誤。async
Promise還提供三種惟一的狀態:函數
Pending
- promise
的結果還沒有肯定,由於將產生其結果的異步操做還沒有完成。Fulfilled
- 異步操做已完成,而且promise
有值。Rejected
- 異步操做失敗,promise
永遠不會實現。在被拒絕狀態下,promise
有一個reason
能夠指示操做失敗的緣由。當promise
在pending
狀態時,它能夠轉換爲fulfilled
或rejected
的狀態。然而,一旦promise
獲得fulfilled
或rejected
,它將永遠不會過渡到任何其餘狀態,其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
爲了不使用JavaScript進行深度嵌套回調,假設能夠簡單地遍歷Promises
,將結果返回給對象或數組,並在完成後中止。不幸的是,這並不容易; 因爲JavaScript的異步特性,若是循環遍歷每一個Promise
,在代碼完成時不會調用「done」
事件。
處理這種狀況的正確方法是使用Promise.all()
。這個函數在它被標記爲已完成以前等待全部的Fulfillments
(或第一次rejection
)。
使用多個嵌套的Promise
調用進行錯誤處理就像蒙着眼睛的駕駛汽車同樣。祝你好運找出哪一個Promise
犯了錯誤。你最好的選擇是徹底刪除catch()
方法並選擇加入全局錯誤處理程序,以下所示:
瀏覽器:
catch()
方法,它將被代碼吞噬。
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
很是容易理解和使用。實際上,它能夠在最新版本的Node.js中本地使用,而且正在迅速融入瀏覽器。如今,若是你想在客戶端使用它,你須要使用Babel。
讓咱們從async
關鍵字開始。它能夠放在function
以前,以下所示:
關鍵字await
使JavaScript等待promise
繼續並返回其結果。以下所示:
如今咱們已經瞭解了Promises
和Async/Await
所提供的不少內容,讓咱們回顧一下爲何Stream認爲Async/Await
是代碼庫的最佳選擇。
Async/Await
容許使用更少的代碼行,更少的輸入和更少的錯誤,提供簡潔明瞭的代碼庫。最終,它使複雜的嵌套代碼再次可讀。try/catch
處理錯誤(在一處,而不是在每一個調用中)Promises
收到的模糊錯誤,它們很大而且很難找到錯誤發生的位置。最重要的是,錯誤指向錯誤發生的函數。能夠說Async/Await
是過去幾年中添加到JavaScript中的最強大的功能之一。
花了不到一天的時間來理解語法,看看咱們的代碼庫在這方面是多麼糟糕。將咱們全部基於Promise
的代碼轉換爲Async/Await
總共花費了大約兩天時間,這其實是一個徹底重寫 - 這只是爲了說明使用Async/Await時須要更少的代碼。