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