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