async/await
你們確定都用過,在處理異步操做的時候真的是很方便。json
若是有還不熟悉的小夥伴能夠看筆者以前的文章:segmentfault
那今天主要講一些在使用 async/await
時容易忽略和犯錯的地方。dom
下面是一個常見的 Vue 代碼片斷:異步
async initStore(query) { await this.getConfig(); await this.getUser(); await this.checkRussianContext(query); await this.getBasket(this.$store.state.config.selectedCurrency), await this.$store.dispatch('options/fetchOptions', { basket : this.$store.state.basket, }); },
上面的代碼中,每一行都會 等待上一行的結果返回後纔會執行。好比其中的 getUser
會等待 getConfig
數據返回以後纔會執行。async
當看到這段代碼時,腦子裏應該注意到如下幾點:工具
Promise.all
?then
進行鏈式調用來避免阻塞剩餘代碼?本篇文章的重點就是經過分析 async/await
可能引起的問題,幫你找到 代碼的壞味道。fetch
讓咱們來看一些具體的數據下的狀況。this
下面是示例代碼:spa
const getUserData = async () => { // 獲取一張隨機的狗狗圖片做爲頭像 const res = await fetch('https://dog.ceo/api/breeds/image/random') const { message } = await res.json() // 獲取隨機生成的用戶信息 const user = await fetch('https://randomuser.me/api/') const { results } = await user.json() // ... }
上面的代碼在 fast 3G
(使用 Chrome 開發者工具)下執行 100 次,平均執行時間爲 1231.10ms
可是很顯然,第二個請求並不須要第一個請求的結果,因此咱們修改爲如下代碼並執行 100 次:
const getUserDataFaster = async () => { // 兩個請求並行執行 const [res, user] = await Promise.all([ fetch('https://dog.ceo/api/breeds/image/random'), fetch('https://randomuser.me/api/') ]) const [{ message }, { results }] = await Promise.all([res.json(), user.json()]) // ... }
咱們獲得的平均執行時間爲 612.50ms,幾乎節省了一半時間。
劃重點:儘量地把查詢請求並行執行。
能夠用這個 codepen 中的代碼體驗
再來例子:
async initStore(query) { await Promise.all([ this.getConfig(), this.getUser(), this.checkRussianContext(query) ]) await this.getBasket(this.$store.state.config.selectedCurrency), await this.$store.dispatch('options/fetchOptions', { basket : this.$store.state.basket, }); await initBooking() },
前面的 3 個請求是並行執行的,而下一段代碼依賴了前面獲取的數據,因此須要在其後執行,可是你有沒有發現其中的問題?
initBooking
這個小可憐只能等到 getBasket
和 fetchOptions
完成以後才能執行,儘管它不須要這兩個方法的任何數據。
一個簡單的解決辦法是將 await
換成 .then
來使用:
關於這個用法能夠看開頭的另外一篇文章
async initStore(query) { await Promise.all([ this.getConfig(), this.getUser(), this.checkRussianContext(query) ]) this.getBasket(this.$store.state.config.selectedCurrency).then(async () => { await this.$store.dispatch('options/fetchOptions', { basket : this.$store.state.basket, }); }) await initBooking() },
這樣的話,getBasket
和 initBooking
均可以並行執行了。
async/await
是 JavaScript 中的一個很是棒的特性,咱們在享受它們便利寫法的同時,也要清楚它們可能引起的問題。有機會審查一下你的代碼,看有沒有能夠並行運行的代碼塊吧~
Thanks for reading~
本文首發於公衆號:碼力全開(codingonfire)
本文隨意轉載哈,註明原文連接便可,公號文章轉載聯繫我開白名單就好~