怎麼處理async/await浪費效能問題
這次帶給大家怎麼處理async/await浪費效能問題,處理async/await浪費效能問題的注意事項有哪些,下面就是實戰案例,一起來看一下。
前言
async/await是什麼
async/await可以說是co模組和產生器函數的語法糖。用更清晰的語意解決js異步程式碼。
熟悉co模組的同學應該都知道,co模組是TJ大神寫的一個使用生成器函數來解決非同步流程的模組,可以看做是生成器函數的執行器。而async/await則是對co模組的升級,內建生成器函數的執行器,不再依賴co模組。同時,async返回的是Promise。
從上面來看,不管是co模組還是async/await,都是將Promise作為最基礎的單元,對Promise不很了解的同學可以先深入了解Promise。
async/await 寫著很爽,不過要注意這些問題。
async/await 讓我們擺脫了回調地獄,但這又引入了 async/await 地獄的問題。
什麼是async/await 地獄
在Javascript 中進行非同步在程式設計的時候,人們總是使用很多await 語句,很多時候我們的語句並不需要依賴先前的語句,這樣就會導致效能問題。
async/await 地獄的例子
#我們試著寫一個購買披薩和飲料的程式:
(async () => { const pizzaData = await getPizzaData() // async call const drinkData = await getDrinkData() // async call const chosenPizza = choosePizza() // sync call const chosenDrink = chooseDrink() // sync call await addPizzaToCart(chosenPizza) // async call await addDrinkToCart(chosenDrink) // async call orderItems() // async call })()
這段程式碼運行沒有問題。但不是一個好的實現,因為這增加了不必要的等待。
說明
我們已經將我們的程式碼封裝在非同步IIFE 中,按照下面的順序執行:
得到披薩名單
取得飲料清單
從清單中選擇一個披薩
從清單中選擇一種飲料
將選取的披薩加入購物車
將所選的飲品加入購物車
訂購購物車中的物品
這裡有個問題為什麼從清單中選擇披薩這個動作要等待取得飲料清單?這兩個是沒什麼關聯的操作。其中的關聯操作有兩組:
取得披薩清單-》 選擇披薩-》 選擇披薩加入購物車
取得飲料清單-》 選擇飲料-》 選擇飲料加入購物車
這兩組運算應該是並發執行的。
再來看一個更差的例子
這個 Javascript 程式碼片段將購物車中的商品並發出訂購請求。
async function orderItems() { const items = await getCartItems() // async call const noOfItems = items.length for(var i = 0; i < noOfItems; i++) { await sendRequest(items[i]) // async call } }
這種情況 for 迴圈必須等待 sendRequest() 函數完成才能繼續下一個迭代。但是,我們並不需要等待。我們希望盡快發送所有請求。然後我們可以等待所有請求完成。
現在你應該已經對 async/await 地獄有跟多的了解,現在我們再來考慮一個問題
如果我們忘記 await 關鍵字會怎麼樣?
如果在呼叫非同步函數忘記使用 await,這表示執行該功能不需要等待。非同步函數將直接傳回一個 promise,你可以稍後使用。
(async () => { const value = doSomeAsyncTask() console.log(value) // an unresolved promise })()
或是程式不清楚你想要等待函數執行完,直接退出不會完成這個非同步任務。所以我們需要使用 await 這個關鍵字。
promise 有一個有趣的屬性,你可以在某行程式碼中取得 promise,然後在其他地方中等待它 resolve,這是解決 async/await 地獄的關鍵。
(async () => { const promise = doSomeAsyncTask() const value = await promise console.log(value) // the actual value })()
如你所見doSomeAsyncTask 直接傳回一個Promise 同時這個非同步函數doSomeAsyncTask 已經開始執行,為了得到doSomeAsyncTask 的回傳值,我們需要await 來告訴
#######應該如何避免async /await 地獄######
首先我们需要知道哪些命名是有前后依赖关系的。
然后将有依赖关系的系列操作进行分组合并成一个异步操作。
同时执行这些异步函数。
我们来重写这写例子:
async function selectPizza() { const pizzaData = await getPizzaData() // async call const chosenPizza = choosePizza() // sync call await addPizzaToCart(chosenPizza) // async call } async function selectDrink() { const drinkData = await getDrinkData() // async call const chosenDrink = chooseDrink() // sync call await addDrinkToCart(chosenDrink) // async call } (async () => { const pizzaPromise = selectPizza() const drinkPromise = selectDrink() await pizzaPromise await drinkPromise orderItems() // async call })() // Although I prefer it this way (async () => { Promise.all([selectPizza(), selectDrink()].then(orderItems) // async call })()
我们将语句分成两个函数。在函数内部,每个语句都依赖于前一个语句的执行。然后我们同时执行这两个函数 selectPizza()和selectDrink() 。
在第二个例子中我们需要处理未知数量的 Promise。处理这个问题非常简单,我们只需要创建一个数组将所有 Promise 存入其中,使用 Promise.all() 方法并行执行:
async function orderItems() { const items = await getCartItems() // async call const noOfItems = items.length const promises = [] for(var i = 0; i < noOfItems; i++) { const orderPromise = sendRequest(items[i]) // async call promises.push(orderPromise) // sync call } await Promise.all(promises) // async call }
相信看了本文案例你已经掌握了方法,更多精彩请关注php中文网其它相关文章!
推荐阅读:
React怎样在react-router路由实现登陆验证控制
以上是怎麼處理async/await浪費效能問題的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

JavaScript是現代Web開發的基石,它的主要功能包括事件驅動編程、動態內容生成和異步編程。 1)事件驅動編程允許網頁根據用戶操作動態變化。 2)動態內容生成使得頁面內容可以根據條件調整。 3)異步編程確保用戶界面不被阻塞。 JavaScript廣泛應用於網頁交互、單頁面應用和服務器端開發,極大地提升了用戶體驗和跨平台開發的靈活性。

Python和JavaScript開發者的薪資沒有絕對的高低,具體取決於技能和行業需求。 1.Python在數據科學和機器學習領域可能薪資更高。 2.JavaScript在前端和全棧開發中需求大,薪資也可觀。 3.影響因素包括經驗、地理位置、公司規模和特定技能。

學習JavaScript不難,但有挑戰。 1)理解基礎概念如變量、數據類型、函數等。 2)掌握異步編程,通過事件循環實現。 3)使用DOM操作和Promise處理異步請求。 4)避免常見錯誤,使用調試技巧。 5)優化性能,遵循最佳實踐。

如何在JavaScript中將具有相同ID的數組元素合併到一個對像中?在處理數據時,我們常常會遇到需要將具有相同ID�...

實現視差滾動和元素動畫效果的探討本文將探討如何實現類似資生堂官網(https://www.shiseido.co.jp/sb/wonderland/)中�...

JavaScript的最新趨勢包括TypeScript的崛起、現代框架和庫的流行以及WebAssembly的應用。未來前景涵蓋更強大的類型系統、服務器端JavaScript的發展、人工智能和機器學習的擴展以及物聯網和邊緣計算的潛力。

深入探討console.log輸出差異的根源本文將分析一段代碼中console.log函數輸出結果的差異,並解釋其背後的原因。 �...
