摘要:正常函數(shù)異常函數(shù)注意當(dāng)返回值本身就是一個(gè)對(duì)象時(shí),函數(shù)的并不會(huì)對(duì)返回值進(jìn)行二次包裝??偸前错樞驁?zhí)行使用函數(shù)之前,我們還得搞清楚它的運(yùn)行機(jī)制。因此在函數(shù)中的并不會(huì)掛起整個(gè)函數(shù)的執(zhí)行。
隨著node 7.6.0正式實(shí)裝async/await函數(shù),js的異步編程變的比以往更加容易。但是,在我們?nèi)嫱度隺sync/await的懷抱之前,有必要對(duì)這個(gè)特性做一些細(xì)致的了解。
書寫形式基本上,任何一個(gè)函數(shù)都可以成為async函數(shù),以下都是合法的書寫形式:
函數(shù)聲明
async function foo () {}
函數(shù)表達(dá)式
const foo = async function () {}
方法定義
const obj = { async foo () {} }
箭頭函數(shù)
async () => {}
即使返回值只是一個(gè)primitive值,async函數(shù)也會(huì)通過(guò)return自動(dòng)將返回值包裝成一個(gè)Promise對(duì)象返回。
因此,下面兩組函數(shù)是等價(jià)的。
// async函數(shù) async function foo () { return "a" } // Promise function foo () { return Promise.resolve("a") }異常 (Reject)
// async函數(shù) async function foo () { throw new Error("error") } // Promise function foo () { return Promise.reject(new Error("error")) }
await總是按順序執(zhí)行注意:當(dāng)返回值本身就是一個(gè)Promise對(duì)象時(shí),async函數(shù)的return并不會(huì)對(duì)返回值進(jìn)行二次包裝。
使用async函數(shù)之前,我們還得搞清楚它的運(yùn)行機(jī)制。尤其是在執(zhí)行順序上,完全用同步的思維也許并不適用于async函數(shù)。
考慮下面的代碼
function asyncGet (x) { return new Promise(resolve => setTimeout(() => { console.log("a") resolve(x) }, 500)) } async function test () { console.log("b") const x = 3 + 5 console.log(x) const a = await asyncGet(1) console.log(a) const b = await asyncGet(2) console.log(b) console.log("c") return a + b } const now = Date.now() console.log("d") test().then(x => { console.log(x) console.log(`elapsed: ${Date.now() - now}`) }) console.log("f")
async函數(shù)和普通函數(shù)一樣按順序執(zhí)行,同時(shí),在執(zhí)行到await語(yǔ)句時(shí),返回一個(gè)Promise對(duì)象
await可以理解為將async函數(shù)掛起,直到等待的Promise被fulfill或者reject,再繼續(xù)執(zhí)行之后的代碼
async函數(shù)的返回值和普通Promise沒有區(qū)別
因此,上面代碼輸出應(yīng)該是
d b 8 f a 1 a 2 c 3 elapsed: 1010
注意 d 和 f 中間的輸出
讓我們?cè)賮?lái)看一個(gè)混合了Promise的版本。
function asyncGet (x) { return new Promise(resolve => setTimeout(() => { console.log("a") resolve(x) }, 500)) } async function test () { console.log("b") const x = 3 + 5 console.log(x) const [a, b] = await Promise.all([ asyncGet(1), asyncGet(2) ]) console.log("c") return a + b } const now = Date.now() console.log("d") test().then(x => { console.log(x) console.log(`elapsed: ${Date.now() - now}`) }) console.log("f")
輸出結(jié)果
d b 8 f a a c 3 elapsed: 509
注意到elapsed的差別了嗎?這就是為什么我們說(shuō)await總是順序執(zhí)行的。不同的await之間無(wú)法并行執(zhí)行,想要真正的完全異步還得借助類似Promise.all這樣的方法。
async函數(shù)和callbackawait只能能影響直接包裹它的async函數(shù)。因此在callback函數(shù)中的await并不會(huì)掛起整個(gè)async函數(shù)的執(zhí)行。
一種常見的錯(cuò)誤
async function getAll (vals) { return vals.map(v => await asyncGet(v)) }
這段代碼有語(yǔ)法錯(cuò)誤,await并不在async函數(shù)內(nèi)部。如果給map的callback加上async呢?
async function getAll (vals) { return vals.map(async v => await asyncGet(v)) }
這段代碼雖然能執(zhí)行,但還有兩個(gè)問(wèn)題。
返回一個(gè)Promise對(duì)象的數(shù)組,并不是我們期待的value數(shù)組
await只會(huì)暫停map的callback,因此map完成時(shí),不能保證asyncGet也全部完成
正確的寫法還得借助Promise.all
async function getAll (vals) { return Promise.all(vals.map(v => asyncGet(v))) }總結(jié)
從上我們可以看出,Promise是async函數(shù)的基礎(chǔ),想要愉快的使用async函數(shù),必須對(duì)Promise有比較深入的理解。甚至一些常見的任務(wù),僅僅依靠async函數(shù)無(wú)法實(shí)現(xiàn)。
希望大家看完本文后能對(duì)async函數(shù)有個(gè)更全面的認(rèn)識(shí),這樣使用起來(lái)才會(huì)更加順手。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/86812.html
摘要:什么是標(biāo)準(zhǔn)引入了函數(shù),使得異步操作變得更加方便。顧名思義是異步的意思,用于聲明一個(gè)函數(shù)是異步的。的作用正常情況下,命令后面是一個(gè)對(duì)象。表示函數(shù)等待返回結(jié)果了,再繼續(xù)執(zhí)行。上面便是一種錯(cuò)誤用法,并沒有在函數(shù)執(zhí)行上下文中,而是在的回調(diào)函數(shù)中。 什么是Async、await ES2017 標(biāo)準(zhǔn)引入了 async 函數(shù),使得異步操作變得更加方便。async顧名思義是異步的意思,用于聲明一個(gè)函數(shù)...
摘要:標(biāo)準(zhǔn)已于年月份正式定稿了,并廣泛支持最新的特性異步函數(shù)。為了領(lǐng)會(huì),我們需要回到普通回調(diào)函數(shù)中進(jìn)一步學(xué)習(xí)。從此編寫回調(diào)函數(shù)不再那么痛苦?;卣{(diào)是一個(gè)函數(shù),可以將結(jié)果傳遞給函數(shù)并在該函數(shù)內(nèi)進(jìn)行調(diào)用,以便作為事件的響應(yīng)。 ES2017標(biāo)準(zhǔn)已于2017年6月份正式定稿了,并廣泛支持最新的特性:異步函數(shù)。如果你曾經(jīng)被異步 JavaScript 的邏輯困擾,這么新函數(shù)正是為你設(shè)計(jì)的。 異步函數(shù)或多或...
摘要:和異步處理調(diào)用訪問(wèn)數(shù)據(jù)采用的方式,這是一個(gè)異步過(guò)程,異步過(guò)程最基本的處理方式是事件或回調(diào),其實(shí)這兩種處理方式實(shí)現(xiàn)原理差不多,都需要在調(diào)用異步過(guò)程的時(shí)候傳入一個(gè)在異步過(guò)程結(jié)束的時(shí)候調(diào)用的接口。 Ajax 和異步處理 調(diào)用 API 訪問(wèn)數(shù)據(jù)采用的 Ajax 方式,這是一個(gè)異步過(guò)程,異步過(guò)程最基本的處理方式是事件或回調(diào),其實(shí)這兩種處理方式實(shí)現(xiàn)原理差不多,都需要在調(diào)用異步過(guò)程的時(shí)候傳入一個(gè)在異...
摘要:,和中新增功能的示例原文鏈接翻譯鏈接始終緊跟的最新功能是很難的,更難的是找到有用的代碼示例。和其他雙字節(jié)字符上的和和其它雙字節(jié)字符串使用的多字節(jié)表示。所以和可能無(wú)法按照預(yù)期的工作。提醒展開運(yùn)算符用于等號(hào)的右側(cè),解構(gòu)運(yùn)算符用于等號(hào)的左側(cè)。 ECMAScript 2016,2017和2018中新增功能的示例 原文鏈接: medium.freecodecamp.org翻譯鏈接:https:/...
摘要:異步函數(shù)是和的組合,基本上,它們是對(duì)的更高級(jí)別的抽象。引入的原因它們降低了對(duì)一些固定語(yǔ)法樣板的要求,打破了鏈?zhǔn)讲荒芮袛噫準(zhǔn)降南拗?。引入?lái)解決著名的回調(diào)地獄問(wèn)題,但是因?yàn)樗麄冏陨淼膹?fù)雜性,引入了更復(fù)雜的語(yǔ)法。 1、簡(jiǎn)介 需先了解 Promise 【鏈接地址】 JavaScript 中的異步函數(shù)方法。 JavaScript 在很短的時(shí)間內(nèi)從回調(diào)演變?yōu)?Promises ,從 ES2...
閱讀 2938·2021-11-22 14:44
閱讀 632·2021-11-22 12:00
閱讀 3772·2019-08-30 15:54
閱讀 1664·2019-08-29 17:15
閱讀 2035·2019-08-29 13:50
閱讀 1198·2019-08-29 13:17
閱讀 3588·2019-08-29 13:05
閱讀 1247·2019-08-29 11:31