国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

精讀《async/await 是把雙刃劍》

2shou / 2779人閱讀

摘要:本周精讀內容是逃離地獄。精讀仔細思考為什么會被濫用,筆者認為是它的功能比較反直覺導致的。同時,筆者認為,也不要過渡利用新特性修復新特性帶來的問題,這樣反而導致代碼可讀性下降。

本周精讀內容是 《逃離 async/await 地獄》。

1 引言

終于,async/await 也被吐槽了。Aditya Agarwal 認為 async/await 語法讓我們陷入了新的麻煩之中。

其實,筆者也早就覺得哪兒不對勁了,終于有個人把實話說了出來,async/await 可能會帶來麻煩。

2 概述

下面是隨處可見的現代化前端代碼:

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

await 語法本身沒有問題,有時候可能是使用者用錯了。當 pizzaDatadrinkData 之間沒有依賴時,順序的 await 會最多讓執行時間增加一倍的 getPizzaData 函數時間,因為 getPizzaDatagetDrinkData 應該并行執行。

回到我們吐槽的回調地獄,雖然代碼比較丑,帶起碼兩行回調代碼并不會帶來阻塞。

看來語法的簡化,帶來了性能問題,而且直接影響到用戶體驗,是不是值得我們反思一下?

正確的做法應該是先同時執行函數,再 await 返回值,這樣可以并行執行異步函數:

(async () => {
  const pizzaPromise = selectPizza();
  const drinkPromise = selectDrink();
  await pizzaPromise;
  await drinkPromise;
  orderItems(); // async call
})();

或者使用 Promise.all 可以讓代碼更可讀:

(async () => {
  Promise.all([selectPizza(), selectDrink()]).then(orderItems); // async call
})();

看來不要隨意的 await,它很可能讓你代碼性能降低。

3 精讀

仔細思考為什么 async/await 會被濫用,筆者認為是它的功能比較反直覺導致的。

首先 async/await 真的是語法糖,功能也僅是讓代碼寫的舒服一些。先不看它的語法或者特性,僅從語法糖三個字,就能看出它一定是局限了某些能力。

舉個例子,我們利用 html 標簽封裝了一個組件,帶來了便利性的同時,其功能一定是 html 的子集。又比如,某個輪子哥覺得某個組件 api 太復雜,于是基于它封裝了一個語法糖,我們多半可以認為這個便捷性是犧牲了部分功能換來的。

功能完整度與使用便利度一直是相互博弈的,很多框架思想的不同開源版本,幾乎都是把功能完整度與便利度按照不同比例混合的結果。

那么回到 async/await 它的解決的問題是回調地獄帶來的災難:

a(() => {
  b(() => {
    c();
  });
});

為了減少嵌套結構太多對大腦造成的沖擊,async/await 決定這么寫:

await a();
await b();
await c();

雖然層級上一致了,但邏輯上還是嵌套關系,這不是另一個程度上增加了大腦負擔嗎?而且這個轉換還是隱形的,所以許多時候,我們傾向于忽略它,所以造成了語法糖的濫用。

理解語法糖

雖然要正確理解 async/await 的真實效果比較反人類,但為了清爽的代碼結構,以及防止寫出低性能的代碼,還是挺有必要認真理解 async/await 帶來的改變。

首先 async/await 只能實現一部分回調支持的功能,也就是僅能方便應對層層嵌套的場景。其他場景,就要動一些腦子了。

比如兩對回調:

a(() => {
  b();
});

c(() => {
  d();
});

如果寫成下面的方式,雖然一定能保證功能一致,但變成了最低效的執行方式:

await a();
await b();
await c();
await d();

因為翻譯成回調,就變成了:

a(() => {
  b(() => {
    c(() => {
      d();
    });
  });
});

然而我們發現,原始代碼中,函數 c 可以與 a 同時執行,但 async/await 語法會讓我們傾向于在 b 執行完后,再執行 c

所以當我們意識到這一點,可以優化一下性能:

const resA = a();
const resC = c();

await resA;
b();
await resC;
d();

但其實這個邏輯也無法達到回調的效果,雖然 ac 同時執行了,但 d 原本只要等待 c 執行完,現在如果 a 執行時間比 c 長,就變成了:

a(() => {
  d();
});

看來只有完全隔離成兩個函數:

(async () => {
  await a();
  b();
})();

(async () => {
  await c();
  d();
})();

或者利用 Promise.all:

async function ab() {
  await a();
  b();
}

async function cd() {
  await c();
  d();
}

Promise.all([ab(), cd()]);

這就是我想表達的可怕之處。回調方式這么簡單的過程式代碼,換成 async/await 居然寫完還要反思一下,再反推著去優化性能,這簡直比回調地獄還要可怕。

而且大部分場景代碼是非常復雜的,同步與 await 混雜在一起,想捋清楚其中的脈絡,并正確優化性能往往是很困難的。但是我們為什么要自己挖坑再填坑呢?很多時候還會導致忘了填。

原文作者給出了 Promise.all 的方式簡化邏輯,但筆者認為,不要一昧追求 async/await 語法,在必要情況下適當使用回調,是可以增加代碼可讀性的。

4 總結

async/await 回調地獄提醒著我們,不要過渡依賴新特性,否則可能帶來的代碼執行效率的下降,進而影響到用戶體驗。同時,筆者認為,也不要過渡利用新特性修復新特性帶來的問題,這樣反而導致代碼可讀性下降。

當我翻開 redux 剛火起來那段時期的老代碼,看到了許多過渡抽象、為了用而用的代碼,硬是把兩行代碼能寫完的邏輯,拆到了 3 個文件,分散在 6 行不同位置,我只好用字符串搜索的方式查找線索,最后發現這個抽象代碼整個項目僅用了一次。

寫出這種代碼的可能性只有一個,就是在精神麻木的情況下,一口氣喝完了 redux 提供的全部雞湯。

就像 async/await 地獄一樣,看到這種 redux 代碼,我覺得遠不如所謂沒跟上時代的老前端寫出的 jquery 代碼。

決定代碼質量的是思維,而非框架或語法,async/await 雖好,但也要適度哦。

5 更多討論
討論地址是:精讀《逃離 async/await 地獄》 · Issue #82 · dt-fe/weekly

如果你想參與討論,請點擊這里,每周都有新的主題,周末或周一發布。

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/94778.html

相關文章

  • 前端進階資源整理

    摘要:前端進階進階構建項目一配置最佳實踐狀態管理之痛點分析與改良開發中所謂狀態淺析從時間旅行的烏托邦,看狀態管理的設計誤區使用更好地處理數據愛彼迎房源詳情頁中的性能優化從零開始,在中構建時間旅行式調試用輕松管理復雜狀態如何把業務邏輯這個故事講好和 前端進階 webpack webpack進階構建項目(一) Webpack 4 配置最佳實踐 react Redux狀態管理之痛點、分析與...

    BlackMass 評論0 收藏0
  • ES6 系列之我們來聊聊 Async

    摘要:標準引入了函數,使得異步操作變得更加方便。在異步處理上,函數就是函數的語法糖。在實際項目中,錯誤處理邏輯可能會很復雜,這會導致冗余的代碼。的出現使得就可以捕獲同步和異步的錯誤。如果有錯誤或者不嚴謹的地方,請務必給予指正,十分感謝。 async ES2017 標準引入了 async 函數,使得異步操作變得更加方便。 在異步處理上,async 函數就是 Generator 函數的語法糖。 ...

    Songlcy 評論0 收藏0
  • 精讀《用 Reduce 實現 Promise 串行執行》

    摘要:引言本周精讀的文章是,講了如何利用實現串行執行。總結串行隊列一般情況下用的不多,因為串行會阻塞,而用戶交互往往是并行的。更多討論討論地址是精讀用實現串行執行如果你想參與討論,請點擊這里,每周都有新的主題,周末或周一發布。 1 引言 本周精讀的文章是 why-using-reduce-to-sequentially-resolve-promises-works,講了如何利用 reduce...

    JinB 評論0 收藏0
  • 精讀《重新思考 Redux》

    摘要:本周精讀內容是重新思考。數據流對數據緩存,性能優化,開發體驗優化都有進一步施展的空間,擁抱插件生態是一個良好的發展方向。 本周精讀內容是 《重新思考 Redux》。 1 引言 《重新思考 Redux》是 rematch 作者 Shawn McKay 寫的一篇干貨軟文。 dva 之后,有許多基于 redux 的狀態管理框架,但大部分都很局限,甚至是倒退。但直到看到了 rematch,總算...

    IntMain 評論0 收藏0
  • 精讀《Nodejs V12》

    摘要:更好的安全性隨著的發布,從升級到了,更安全且更易配置。通過使用,程序可以減少握手所需時間來提升請求性能。提供診斷報告有一項實驗功能,根據用戶需求提供診斷報告,包括崩潰性能下降內存泄露使用高等等。前端精讀幫你篩選靠譜的內容。 1. 引言 Node12 發布有幾個月了,讓我們跟隨 Nodejs 12 一起看看 Node12 帶來了哪些改變。 2. 概述 Node12 與以往的版本不同,帶來...

    CoderStudy 評論0 收藏0

發表評論

0條評論

最新活動
閱讀需要支付1元查看
<