摘要:這只是一個(gè)更優(yōu)雅的得到值的語(yǔ)句,它比更加容易閱讀和書寫??偨Y(jié)放在一個(gè)函數(shù)前的有兩個(gè)作用使函數(shù)總是返回一個(gè)允許在這其中使用前面的關(guān)鍵字能夠使等待,直到處理結(jié)束。
Async/await 寫在前面
渣渣新人的首篇外文文章翻譯!!存在錯(cuò)誤可能會(huì)很多,如有錯(cuò)誤,煩請(qǐng)各位大大指正出來(lái),感謝!
本篇為翻譯!
本篇為翻譯!
本篇為翻譯!
原文文章地址:https://javascript.info/async-awaitAsync/await
有一種特殊的語(yǔ)法可以更舒適地與promise協(xié)同工作,它叫做async/await,它是非常的容易理解和使用。
Async functions讓我們先從async關(guān)鍵字說(shuō)起,它被放置在一個(gè)函數(shù)前面。就像下面這樣:
async function f() { return 1 }
函數(shù)前面的async一詞意味著一個(gè)簡(jiǎn)單的事情:這個(gè)函數(shù)總是返回一個(gè)promise,如果代碼中有return <非promise>語(yǔ)句,JavaScript會(huì)自動(dòng)把返回的這個(gè)value值包裝成promise的resolved值。
例如,上面的代碼返回resolved值為1的promise,我們可以測(cè)試一下:
async function f() { return 1 } f().then(alert) // 1
我們也可以顯式的返回一個(gè)promise,這個(gè)將會(huì)是同樣的結(jié)果:
async function f() { return Promise.resolve(1) } f().then(alert) // 1
所以,async確保了函數(shù)返回一個(gè)promise,即使其中包含非promise。夠簡(jiǎn)單了吧?但是不僅僅只是如此,還有另一個(gè)關(guān)鍵詞await,只能在async函數(shù)里使用,同樣,它也很cool。
Await語(yǔ)法如下:
// 只能在async函數(shù)內(nèi)部使用 let value = await promise
關(guān)鍵詞await可以讓JavaScript進(jìn)行等待,直到一個(gè)promise執(zhí)行并返回它的結(jié)果,JavaScript才會(huì)繼續(xù)往下執(zhí)行。
以下是一個(gè)promise在1s之后resolve的例子:
async function f() { let promise = new Promise((resolve, reject) => { setTimeout(() => resolve("done!"), 1000) }) let result = await promise // 直到promise返回一個(gè)resolve值(*) alert(result) // "done!" } f()
函數(shù)執(zhí)行到(*)行會(huì)‘暫?!?,當(dāng)promise處理完成后重新恢復(fù)運(yùn)行, resolve的值成了最終的result,所以上面的代碼會(huì)在1s后輸出"done!"
我們強(qiáng)調(diào)一下:await字面上使得JavaScript等待,直到promise處理完成,
然后將結(jié)果繼續(xù)下去。這并不會(huì)花費(fèi)任何的cpu資源,因?yàn)橐婺軌蛲瑫r(shí)做其他工作:執(zhí)行其他腳本,處理事件等等。
這只是一個(gè)更優(yōu)雅的得到promise值的語(yǔ)句,它比promise更加容易閱讀和書寫。
不能在常規(guī)函數(shù)里使用await
如果我們?cè)噲D在非async函數(shù)里使用await,就會(huì)出現(xiàn)一個(gè)語(yǔ)法錯(cuò)誤:function f() { let promise = Promise.resolve(1) let result = await promise // syntax error }如果我們忘記了在函數(shù)之前放置async,我們就會(huì)得到這樣一個(gè)錯(cuò)誤。如上所述,await只能在async函數(shù)中工作。
讓我們來(lái)看promise鏈?zhǔn)讲僮饕徽轮刑岬降?b>showAvatar()例子,并用async/await重寫它。
1.我們需要將.then()替換為await
2.此外,我們應(yīng)該讓函數(shù)變成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()
相當(dāng)?shù)暮?jiǎn)潔和易讀,比以前的要好得多。
await不能工作在頂級(jí)作用域
那些剛開始使用await的人們老是忘記這一點(diǎn),那就是我們不能將await放在代碼的頂層,那樣是行不通的:// 頂層代碼處syntax error let response = await fetch("/article/promise-chaining/user.json") let user = await response.json()所以我們需要將await代碼包裹在一個(gè)async函數(shù)中,就像上面的例子一樣。
await接受thenables(好吧我這個(gè)渣渣并不知道thenables該如何翻譯,有人能告知嗎?)
就像promise.then,await也允許使用thenable對(duì)象(那些具有可調(diào)用的then方法的對(duì)象)。同樣,第三方對(duì)象可能不是一個(gè)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變?yōu)? let result = await new Thenable(1) alert(result) } f()如果await得到了一個(gè)帶有then方法的非promise對(duì)象,它將會(huì)調(diào)用提供原生函數(shù)resolve、reject作為參數(shù)的方法,然后await一直等待,直到他們其中的一個(gè)被調(diào)用(在上面的例子它發(fā)生在(*)行)。
錯(cuò)誤處理async方法
一個(gè)class方法同樣能夠使用async,只需要將async放在它之前就可以
就像這樣:class Waiter { async wait () { return await Promise.resolve(1) } } new Waiter().wait().then(alert) // 1這里的意思是一樣的:它確保了返回值是一個(gè)promise,支持await
如果一個(gè)promise正常resolve,那么await返回這個(gè)結(jié)果,但是在reject的情況下會(huì)拋出一個(gè)錯(cuò)誤,就好像在那一行有一個(gè)throw語(yǔ)句一樣。
async function f() { await Promise.reject(new Error("whoops!")) }
和下面一樣
async function f() { throw new Error("Whoops!") }
在真實(shí)的使用場(chǎng)景中,promise在reject拋出錯(cuò)誤之前可能需要一段時(shí)間,所以await將會(huì)等待,然后才拋出一個(gè)錯(cuò)誤。
我們可以使用try-catch語(yǔ)句捕獲錯(cuò)誤,就像在正常拋出中處理異常一樣:
async function f() { try { let response = await fetch("http://no-such-url") } catch (err) { alet(err) // TypeError: failed to fetch } } f()
如果發(fā)生了一個(gè)錯(cuò)誤,控制會(huì)跳轉(zhuǎn)到catch塊。當(dāng)然我們也能夠捕獲多行語(yǔ)句:
async function f() { try { let response = await fetch("/no-user-here") let user = await response.json() } catch(err) { // 在fetch和response.json中都能捕獲錯(cuò)誤 alert(err) } } f()
如果我們不使用try-catch,然后async函數(shù)f()的調(diào)用產(chǎn)生的promise變成reject狀態(tài)的話,我們可以添加.catch去處理它:
async function f() { let response = await fetch("http://no-such-url") } // f()變成了一個(gè)rejected的promise f().catch(alert) // TypeError: failed to fetch
如果我們忘記添加.catch,我們就會(huì)得到一個(gè)未被處理的promise錯(cuò)誤(能夠在控制臺(tái)里看到它),這時(shí)我們可以通過(guò)使用一個(gè)全局的事件處理器去捕獲錯(cuò)誤,就像在Promise鏈?zhǔn)讲僮饕徽轮v的那樣。
async/await和promise.then/catch
當(dāng)我們使用async/await,我們很少需要.then,因?yàn)閍wait總是等待著我們,而且我們能夠使用常規(guī)的try-catch而不是.catch,這通常(并不總是)更方便。但是在代碼的頂層,當(dāng)我們?cè)赼sync函數(shù)的外部時(shí),我們?cè)谡Z(yǔ)法上是不能使用await的,所以通常添加.then/catch去處理最終結(jié)果或者錯(cuò)誤。
總結(jié)async/await能夠與Promise.all友好的協(xié)作
當(dāng)我們需要等待多個(gè)promise時(shí),我們可以將他們包裝在Promise.all中然后使用await:// 直到數(shù)組全部返回結(jié)果 let results = await Promise.all([ fetch(url1), fetch(url2), ... ])如果發(fā)生了一個(gè)錯(cuò)誤,它就像普通情況一樣:從一個(gè)失敗狀態(tài)的promise到Promise.all,然后變成了一個(gè)我們能夠使用try-cathc去捕獲的異常。
放在一個(gè)函數(shù)前的async有兩個(gè)作用:
1.使函數(shù)總是返回一個(gè)promise
2.允許在這其中使用await
promise前面的await關(guān)鍵字能夠使JavaScript等待,直到promise處理結(jié)束。然后:
1.如果它是一個(gè)錯(cuò)誤,異常就產(chǎn)生了,就像在那個(gè)地方調(diào)用了throw error一樣。
2.否則,它會(huì)返回一個(gè)結(jié)果,我們可以將它分配給一個(gè)值
他們一起提供了一個(gè)很好的框架來(lái)編寫易于讀寫的異步代碼。
有了async/await,我們很少需要寫promise.then/catch,但是我們?nèi)匀徊粦?yīng)該忘記它們是基于promise的,因?yàn)橛行r(shí)候(例如在最外面的范圍內(nèi))我們不得不使用這些方法。Promise.all也是一個(gè)非常棒的東西,它能夠同時(shí)等待很多任務(wù)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/107501.html
摘要:等待的基本語(yǔ)法該關(guān)鍵字的的意思就是讓編譯器等待并返回結(jié)果。這里并不會(huì)占用資源,因?yàn)橐婵梢酝瑫r(shí)執(zhí)行其他任務(wù)其他腳本或處理事件。接下來(lái),我們寫一個(gè)火箭發(fā)射場(chǎng)景的小例子不是真的發(fā)射火箭 本文由云+社區(qū)發(fā)表 本篇文章,小編將和大家一起學(xué)習(xí)異步編程的未來(lái)——async/await,它會(huì)打破你對(duì)上篇文章Promise的認(rèn)知,竟然異步代碼還能這么寫! 但是別太得意,你需要深入理解Promise后,...
摘要:原因是的循環(huán)方法等是并行迭代,可以理解為的效果是無(wú)效的解決方案使用最原始的循環(huán)將上述的模擬異步任務(wù)修改為或參考連接用來(lái)處理異步在不起作用解決異步循環(huán)的使用方法 問(wèn)題描述 在進(jìn)行業(yè)務(wù)開發(fā)的過(guò)程中,使用了數(shù)組的高級(jí)函數(shù)map,同時(shí)使用了ES6語(yǔ)法async/await,發(fā)現(xiàn)在map循環(huán)下任務(wù)是異步執(zhí)行的,并不符合預(yù)期 例子說(shuō)明 /** * 異步打印數(shù)據(jù) */ const echo =...
摘要:傳統(tǒng)回調(diào)函數(shù)現(xiàn)在我們要做個(gè)事情,寫個(gè)回調(diào)函數(shù),每秒輸出一個(gè)遞增的數(shù)字,輸出三次普通回調(diào)函數(shù)的寫法現(xiàn)在調(diào)用它現(xiàn)在我們改用來(lái)重寫的函數(shù)我們?cè)谶@里暴露那個(gè)以供調(diào)用現(xiàn)在使用它這里把這個(gè)暴露出去以供使用,記得把本的調(diào)用函數(shù)注釋掉就是行注釋掉 傳統(tǒng)回調(diào)函數(shù) // demo1-callback.js /** 現(xiàn)在我們要做個(gè)事情,寫個(gè)回調(diào)函數(shù),每秒輸出一個(gè)遞增的數(shù)字,輸出三次 普通回調(diào)...
摘要:有兩個(gè)陌生的關(guān)鍵字,同時(shí)函數(shù)執(zhí)行結(jié)果似乎返回了一個(gè)對(duì)象。用來(lái)表示函數(shù)是異步的,定義的函數(shù)會(huì)返回一個(gè)對(duì)象,可以使用方法添加回調(diào)函數(shù)。如果的是對(duì)象會(huì)造成異步函數(shù)停止執(zhí)行并且等待的解決如果等的是正常的表達(dá)式則立即執(zhí)行。 視頻講解 關(guān)于異步處理,ES5的回調(diào)使我們陷入地獄,ES6的Promise使我們脫離魔障,終于、ES7的async-await帶我們走向光明。今天就來(lái)學(xué)習(xí)一下 async-a...
Promise/async、await幫我們解決了什么 它給我們提供了一種新的異步編程解決方案,同時(shí)避免了困擾已久的回調(diào)地獄 // 異步的處理可能會(huì)產(chǎn)生這樣的回調(diào)地獄(第二個(gè)異步操作和第一個(gè)異步的結(jié)果有關(guān)系) let Ajax = function(data, success, error){ $.ajax({ data: data, success: function...
閱讀 698·2021-11-15 11:37
閱讀 4189·2021-09-09 09:34
閱讀 3593·2019-08-30 15:52
閱讀 2632·2019-08-29 14:03
閱讀 2871·2019-08-26 13:36
閱讀 1618·2019-08-26 12:16
閱讀 1620·2019-08-26 11:45
閱讀 3513·2019-08-23 18:41