摘要:這只是一個更優雅的得到值的語句,它比更加容易閱讀和書寫。總結放在一個函數前的有兩個作用使函數總是返回一個允許在這其中使用前面的關鍵字能夠使等待,直到處理結束。
Async/await 寫在前面
渣渣新人的首篇外文文章翻譯!!存在錯誤可能會很多,如有錯誤,煩請各位大大指正出來,感謝!
本篇為翻譯!
本篇為翻譯!
本篇為翻譯!
原文文章地址:https://javascript.info/async-awaitAsync/await
有一種特殊的語法可以更舒適地與promise協同工作,它叫做async/await,它是非常的容易理解和使用。
Async functions讓我們先從async關鍵字說起,它被放置在一個函數前面。就像下面這樣:
async function f() { return 1 }
函數前面的async一詞意味著一個簡單的事情:這個函數總是返回一個promise,如果代碼中有return <非promise>語句,JavaScript會自動把返回的這個value值包裝成promise的resolved值。
例如,上面的代碼返回resolved值為1的promise,我們可以測試一下:
async function f() { return 1 } f().then(alert) // 1
我們也可以顯式的返回一個promise,這個將會是同樣的結果:
async function f() { return Promise.resolve(1) } f().then(alert) // 1
所以,async確保了函數返回一個promise,即使其中包含非promise。夠簡單了吧?但是不僅僅只是如此,還有另一個關鍵詞await,只能在async函數里使用,同樣,它也很cool。
Await語法如下:
// 只能在async函數內部使用 let value = await promise
關鍵詞await可以讓JavaScript進行等待,直到一個promise執行并返回它的結果,JavaScript才會繼續往下執行。
以下是一個promise在1s之后resolve的例子:
async function f() { let promise = new Promise((resolve, reject) => { setTimeout(() => resolve("done!"), 1000) }) let result = await promise // 直到promise返回一個resolve值(*) alert(result) // "done!" } f()
函數執行到(*)行會‘暫停’,當promise處理完成后重新恢復運行, resolve的值成了最終的result,所以上面的代碼會在1s后輸出"done!"
我們強調一下:await字面上使得JavaScript等待,直到promise處理完成,
然后將結果繼續下去。這并不會花費任何的cpu資源,因為引擎能夠同時做其他工作:執行其他腳本,處理事件等等。
這只是一個更優雅的得到promise值的語句,它比promise更加容易閱讀和書寫。
不能在常規函數里使用await
如果我們試圖在非async函數里使用await,就會出現一個語法錯誤:function f() { let promise = Promise.resolve(1) let result = await promise // syntax error }如果我們忘記了在函數之前放置async,我們就會得到這樣一個錯誤。如上所述,await只能在async函數中工作。
讓我們來看promise鏈式操作一章中提到的showAvatar()例子,并用async/await重寫它。
1.我們需要將.then()替換為await
2.此外,我們應該讓函數變成async,這樣await才能夠工作
async function showAvatar() { // read our JSON let response = await fetch("/article/promise-chaining/user.json") let user = await response.json() // read github user let githubResponse = await fetch(`https://api.github.com/users/${user.name}`) let githubUser = await githubResponse.json() // 展示頭像 let img = document.createElement("img") img.src = githubUser.avatar_url img.className = "promise-avatar-example" documenmt.body.append(img) // 等待3s await new Promise((resolve, reject) => { setTimeout(resolve, 3000) }) img.remove() return githubUser } showAvatar()
相當的簡潔和易讀,比以前的要好得多。
await不能工作在頂級作用域
那些剛開始使用await的人們老是忘記這一點,那就是我們不能將await放在代碼的頂層,那樣是行不通的:// 頂層代碼處syntax error let response = await fetch("/article/promise-chaining/user.json") let user = await response.json()所以我們需要將await代碼包裹在一個async函數中,就像上面的例子一樣。
await接受thenables(好吧我這個渣渣并不知道thenables該如何翻譯,有人能告知嗎?)
就像promise.then,await也允許使用thenable對象(那些具有可調用的then方法的對象)。同樣,第三方對象可能不是一個promise,但是promise的兼容性表示,如果它支持.then方法,那么它就能用于await。
例如,這里await接受了new Thenable(1)
class Thenable { constructor(num) { this.num = num } then(resolve, reject) { alert(resolve) // function() {native code} // 1000ms后將this.num*2作為resolve值 setTimeout(()=> {resolve(this.num * 2), 1000}) } } async function(f) { // 等待1s,result變為2 let result = await new Thenable(1) alert(result) } f()如果await得到了一個帶有then方法的非promise對象,它將會調用提供原生函數resolve、reject作為參數的方法,然后await一直等待,直到他們其中的一個被調用(在上面的例子它發生在(*)行)。
錯誤處理async方法
一個class方法同樣能夠使用async,只需要將async放在它之前就可以
就像這樣:class Waiter { async wait () { return await Promise.resolve(1) } } new Waiter().wait().then(alert) // 1這里的意思是一樣的:它確保了返回值是一個promise,支持await
如果一個promise正常resolve,那么await返回這個結果,但是在reject的情況下會拋出一個錯誤,就好像在那一行有一個throw語句一樣。
async function f() { await Promise.reject(new Error("whoops!")) }
和下面一樣
async function f() { throw new Error("Whoops!") }
在真實的使用場景中,promise在reject拋出錯誤之前可能需要一段時間,所以await將會等待,然后才拋出一個錯誤。
我們可以使用try-catch語句捕獲錯誤,就像在正常拋出中處理異常一樣:
async function f() { try { let response = await fetch("http://no-such-url") } catch (err) { alet(err) // TypeError: failed to fetch } } f()
如果發生了一個錯誤,控制會跳轉到catch塊。當然我們也能夠捕獲多行語句:
async function f() { try { let response = await fetch("/no-user-here") let user = await response.json() } catch(err) { // 在fetch和response.json中都能捕獲錯誤 alert(err) } } f()
如果我們不使用try-catch,然后async函數f()的調用產生的promise變成reject狀態的話,我們可以添加.catch去處理它:
async function f() { let response = await fetch("http://no-such-url") } // f()變成了一個rejected的promise f().catch(alert) // TypeError: failed to fetch
如果我們忘記添加.catch,我們就會得到一個未被處理的promise錯誤(能夠在控制臺里看到它),這時我們可以通過使用一個全局的事件處理器去捕獲錯誤,就像在Promise鏈式操作一章講的那樣。
async/await和promise.then/catch
當我們使用async/await,我們很少需要.then,因為await總是等待著我們,而且我們能夠使用常規的try-catch而不是.catch,這通常(并不總是)更方便。但是在代碼的頂層,當我們在async函數的外部時,我們在語法上是不能使用await的,所以通常添加.then/catch去處理最終結果或者錯誤。
總結async/await能夠與Promise.all友好的協作
當我們需要等待多個promise時,我們可以將他們包裝在Promise.all中然后使用await:// 直到數組全部返回結果 let results = await Promise.all([ fetch(url1), fetch(url2), ... ])如果發生了一個錯誤,它就像普通情況一樣:從一個失敗狀態的promise到Promise.all,然后變成了一個我們能夠使用try-cathc去捕獲的異常。
放在一個函數前的async有兩個作用:
1.使函數總是返回一個promise
2.允許在這其中使用await
promise前面的await關鍵字能夠使JavaScript等待,直到promise處理結束。然后:
1.如果它是一個錯誤,異常就產生了,就像在那個地方調用了throw error一樣。
2.否則,它會返回一個結果,我們可以將它分配給一個值
他們一起提供了一個很好的框架來編寫易于讀寫的異步代碼。
有了async/await,我們很少需要寫promise.then/catch,但是我們仍然不應該忘記它們是基于promise的,因為有些時候(例如在最外面的范圍內)我們不得不使用這些方法。Promise.all也是一個非常棒的東西,它能夠同時等待很多任務。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/107501.html
摘要:等待的基本語法該關鍵字的的意思就是讓編譯器等待并返回結果。這里并不會占用資源,因為引擎可以同時執行其他任務其他腳本或處理事件。接下來,我們寫一個火箭發射場景的小例子不是真的發射火箭 本文由云+社區發表 本篇文章,小編將和大家一起學習異步編程的未來——async/await,它會打破你對上篇文章Promise的認知,竟然異步代碼還能這么寫! 但是別太得意,你需要深入理解Promise后,...
摘要:原因是的循環方法等是并行迭代,可以理解為的效果是無效的解決方案使用最原始的循環將上述的模擬異步任務修改為或參考連接用來處理異步在不起作用解決異步循環的使用方法 問題描述 在進行業務開發的過程中,使用了數組的高級函數map,同時使用了ES6語法async/await,發現在map循環下任務是異步執行的,并不符合預期 例子說明 /** * 異步打印數據 */ const echo =...
摘要:傳統回調函數現在我們要做個事情,寫個回調函數,每秒輸出一個遞增的數字,輸出三次普通回調函數的寫法現在調用它現在我們改用來重寫的函數我們在這里暴露那個以供調用現在使用它這里把這個暴露出去以供使用,記得把本的調用函數注釋掉就是行注釋掉 傳統回調函數 // demo1-callback.js /** 現在我們要做個事情,寫個回調函數,每秒輸出一個遞增的數字,輸出三次 普通回調...
摘要:有兩個陌生的關鍵字,同時函數執行結果似乎返回了一個對象。用來表示函數是異步的,定義的函數會返回一個對象,可以使用方法添加回調函數。如果的是對象會造成異步函數停止執行并且等待的解決如果等的是正常的表達式則立即執行。 視頻講解 關于異步處理,ES5的回調使我們陷入地獄,ES6的Promise使我們脫離魔障,終于、ES7的async-await帶我們走向光明。今天就來學習一下 async-a...
Promise/async、await幫我們解決了什么 它給我們提供了一種新的異步編程解決方案,同時避免了困擾已久的回調地獄 // 異步的處理可能會產生這樣的回調地獄(第二個異步操作和第一個異步的結果有關系) let Ajax = function(data, success, error){ $.ajax({ data: data, success: function...
閱讀 672·2021-11-15 11:37
閱讀 4127·2021-09-09 09:34
閱讀 3567·2019-08-30 15:52
閱讀 2608·2019-08-29 14:03
閱讀 2849·2019-08-26 13:36
閱讀 1592·2019-08-26 12:16
閱讀 1599·2019-08-26 11:45
閱讀 3490·2019-08-23 18:41