欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

async/await地獄該如何避免詳解

 更新時間:2018年05月10日 08:36:17   作者:極光推送  
這篇文章主要給大家介紹了關于async/await地獄該如何避免的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。

前言

async/await是什么

async/await可以說是co模塊和生成器函數的語法糖。用更加清晰的語義解決js異步代碼。

熟悉co模塊的同學應該都知道,co模塊是TJ大神寫的一個使用生成器函數來解決異步流程的模塊,可以看做是生成器函數的執(zhí)行器。而async/await則是對co模塊的升級,內置生成器函數的執(zhí)行器,不再依賴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 中,按照下面的順序執(zhí)行:

得到披薩名單
獲取飲料列表
從列表中選擇一個披薩
從列表中選擇一種飲料
將選中的披薩加入購物車
將選擇的飲品加入購物車
訂購購物車中的物品

問題

這里有個問題為什么從列表中選擇披薩這個動作要等待獲取飲料列表?這兩個是沒什么關聯(lián)的操作。其中的關聯(lián)操作有兩組:

獲取披薩列表 -》 選擇披薩 -》 選擇披薩加入購物車

獲取飲料列表 -》 選擇飲料 -》 選擇飲料加入購物車

這兩組操作應該是并發(fā)執(zhí)行的。

再來看一個更差的例子

這個 Javascript 代碼片段將購物車中的商品并發(fā)出訂購請求。

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 循環(huán)必須等待 sendRequest() 函數完成才能繼續(xù)下一次迭代。但是,我們并不需要等待。我們希望盡快發(fā)送所有請求。然后我們可以等待所有請求完成。

現在你應該已經對 async/await 地獄有跟多的了解,現在我們再來考慮一個問題

如果我們忘記 await 關鍵字會怎么樣?

如果在調用異步函數忘記使用 await,這意味著執(zhí)行該功能不需要等待。異步函數將直接返回一個 promise,你可以稍后使用。

(async () => {
 const value = doSomeAsyncTask()
 console.log(value) // an unresolved promise
})()

或者是程序不清楚你想要等待函數執(zhí)行完,直接退出不會完成這個異步任務。所以我們需要使用 await 這個關鍵字。

promise 有一個有趣的屬性,你可以在某行代碼中獲取 promise,然后在其他地方中等待它 resolve,這是解決 async/await 地獄的關鍵。

(async () => {
 const promise = doSomeAsyncTask()
 const value = await promise
 console.log(value) // the actual value
})()

如你所見 doSomeAsyncTask 直接返回一個 Promise 同時這個異步函數 doSomeAsyncTask 已經開始執(zhí)行,為了得到 doSomeAsyncTask 的返回值,我們需要 await 來告訴

應該如何避免 async/await 地獄

首先我們需要知道哪些命名是有前后依賴關系的。

然后將有依賴關系的系列操作進行分組合并成一個異步操作。

同時執(zhí)行這些異步函數。

我們來重寫這寫例子:

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
})()

我們將語句分成兩個函數。在函數內部,每個語句都依賴于前一個語句的執(zhí)行。然后我們同時執(zhí)行這兩個函數 selectPizza()和selectDrink() 。

在第二個例子中我們需要處理未知數量的 Promise。處理這個問題非常簡單,我們只需要創(chuàng)建一個數組將所有 Promise 存入其中,使用 Promise.all() 方法并行執(zhí)行:

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
}

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關文章

  • js原生map實現的方法總結

    js原生map實現的方法總結

    在本篇文章里小編給大家整理了關于js原生map實現的方法以及實例分析內容,需要的朋友們可以參考下。
    2020-01-01
  • JS實現的ajax和同源策略(實例講解)

    JS實現的ajax和同源策略(實例講解)

    下面小編就為大家分享一篇JS實現的ajax和同源策略的實例講解,具有很好的參考價值,希望對大家有所幫助
    2017-12-12
  • Bootstrap select實現下拉框多選效果

    Bootstrap select實現下拉框多選效果

    這篇文章主要為大家詳細介紹了Bootstrap select實現下拉框多選效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • js中string和number類型互轉換技巧(分享)

    js中string和number類型互轉換技巧(分享)

    下面小編就為大家?guī)硪黄猨s中string和number類型互轉換技巧(分享)。小編覺得挺不錯的,現在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2016-11-11
  • 微信小程序地圖標記多個位置的方法詳解

    微信小程序地圖標記多個位置的方法詳解

    地圖是我們平時經常用到的組件,而且地圖是顯示在最高層的原生組件,下面這篇文章主要給大家介紹了關于微信小程序地圖標記多個位置的相關資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2022-04-04
  • JavaScript中自定義swiper組件詳解

    JavaScript中自定義swiper組件詳解

    這篇文章主要介紹了微信小程序 swiper組件輪播圖詳解及實例的相關資料,需要的朋友可以參考下,希望能給你帶來幫助
    2021-08-08
  • js中作用域的實例解析

    js中作用域的實例解析

    本文主要通過幾個實例對js中作用域進行詳細解析,具有很好的參考價值。下面跟著小編一起來看下吧
    2017-03-03
  • js實現登錄注冊框手機號和驗證碼校驗(前端部分)

    js實現登錄注冊框手機號和驗證碼校驗(前端部分)

    這篇文章主要為大家詳細介紹了js實現登錄注冊框手機號和驗證碼校驗的前端部分代碼,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-09-09
  • javascript用DIV模擬彈出窗口_窗體滾動跟隨

    javascript用DIV模擬彈出窗口_窗體滾動跟隨

    可滾動跟隨彈出框效果代碼,非常實用的應用于網絡廣告
    2008-09-09
  • JS Tween 顏色漸變

    JS Tween 顏色漸變

    從我寫的as tween改寫的,基本功能跟as里面寫的一樣,只是沒有擴展特定功能的接口(比如alpha2,move2,size2,color2等接口,這些在as tween里面都有實現)。
    2008-12-12

最新評論