在很長一段時間裏,JavaScript 開發人員不得不依賴回調來處理異步代碼。所以,咱們中的許多人都經歷過回調地獄,當面對這樣的函數時,咱們會感到無賴javascript
不過好在JavaScript提供了,.then()的一種回覆方式,目前也有不少人正在用他java
如今,隨着 Async/Await 的最新增長,編寫 JavaScript 代碼將會變得更加優雅!ios
Async/Await 是一個期待已久的 JavaScript 特性,它使得使用異步函數變得更加愉快和更容易理解。它創建在 Promises 之上,並與全部現有的基於 promise 的 api 兼容json
這個名字來自 async 和 await ——這兩個關鍵詞能夠幫助咱們清理異步代碼:axios
Async-聲明一個異步函數(Async function someName (){ ... })api
Await-暫停 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 時,咱們仍然在引擎蓋下使用 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 的另外一個優勢是,它容許咱們在一個很好在 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 開發者和資深編碼者的青睞
文章屬於翻譯,做者:羊先生
英文原文