成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

為什么 Async/Await 不僅僅是句法糖

開發 前端
異步編程在 JavaScript 中很常見。每當我們需要進行網絡服務調用、文件訪問或數據庫操作時,盡管語言是單線程的,但異步性是我們防止用戶界面被阻塞的方法。

開篇觀點,async/await? 不僅僅是 Promise 上面的語法糖,因為 async/await 確實提供了切實的好處。

  • async/await 讓異步代碼變成同步的方式,從而使代碼更具表現力和可讀性。
  • async/await 統一了異步編程的經驗;以及提供了更好的錯誤堆棧跟蹤。

關于 JS 中異步編程的一點歷史

異步編程在 JavaScript 中很常見。每當我們需要進行網絡服務調用、文件訪問或數據庫操作時,盡管語言是單線程的,但異步性是我們防止用戶界面被阻塞的方法。

在  ES6 之前,回調是猿們處理異步編程的方式。我們表達時間依賴性(即異步操作的執行順序)的唯一方法是將一個回調嵌套在另一個回調中,這導致了所謂的回調地獄。

Es6 中引入了 Promise?,它是一個用于異步操作的一流對象,我們可以輕松地傳遞、組合、聚合和應用轉換。時間上的依賴性通過 then方法鏈干凈地表達出來。

有了 Promise 這個強大的伙伴,聽起來異步編程在 JS 中是一個已經解決的問題,對嗎?

恩,還沒有,因為有時候 Promise 的級別太低了,不太適合使用。

有時 Promise 的級別太低,不適合使用

盡管出現了 Promise,但在 JS 中仍然需要一個更高級別的語言結構來進行異步編程。

我們來看個例子, 假設我們需要某個函數在某個時間間隔輪詢一個API。當達到最大重試次數時,它就會解析為 null。

下面是 Promise 的一種解決方案:

let count = 0;

function apiCall() {
return new Promise((resolve) =>
// a在第6次重試時,它被解析為 "value"
count++ === 5 ? resolve('value') : resolve(null)
);
}

function sleep(interval) {
return new Promise((resolve) => setTimeout(resolve, interval));
}

function poll(retry, interval) {
return new Promise((resolve) => {
// 為了簡潔起見,跳過錯誤處理

if (retry === 0) resolve(null);
apiCall().then((val) => {
if (val !== null) resolve(val);
else {
sleep(interval).then(() => {
resolve(poll(retry - 1, interval));
});
}
});
});
}

poll(6, 1000).then(console.log); // 'value'

這種解決方案的直觀性和可讀性取決于人們對Promise的熟悉程度,以及 Promise.resolve 如何 "平鋪" Promise 和遞歸。對我來說,這不是寫這樣一個函數的最可讀的方式。

使用 async/await

我們用 async/await 語法重寫上述解決方案:

async function poll(retry, interval) {
while (retry >= 0) {
const value = await apiCall().catch((e) => {});
if (value !== null) return value;
await sleep(interval);
retry--;
}

return null;
}

我想大多數人都會覺得上面的解決方案更有可讀性,因為我們能夠使用所有正常的語言結構,如循環、異步操作的 try-catch 等。

這可能是 async/await? 的最大賣點--使我們能夠以同步的方式編寫異步代碼。另一方面,這可能是對 async/await 最常見的反對意見的來源,稍后再談這個問題。

順便說一下,await?甚至有正確的操作符優先級,所以await a + await b? 等于(await a) + (await b)?,而不是讓我們說await (a + await b)。

async/await 在同步和異步代碼中提供了統一的體驗

async/await?的另一個好處是,await?自動將任何非Promise(non-thenables)包裝成 Promises 。await?的語義等同于Promise.resolve?,這意味著可以 await 任何東西:

function fetchValue() {
return 1;
}

async function fn() {
const val = await fetchValue();
console.log(val); // 1
}

// 上面等同于下面

function fn() {
Promise.resolve(fetchValue()).then((val) => {
console.log(val); // 1
});
}

如果我們將 then? 方法附加到從 fetchValue? 返回的數字 1 上,就會出現以下錯誤。

function fetchValue() {
return 1;
}

function fn() {
fetchValue().then((val) => {
console.log(val);
});
}

fn(); // ? Uncaught TypeError: fetchValue(...).then is not a function

最后, 從 async 函數返回的任何東西都是一個 Promise:

Object.prototype.toString.call((async function () {})()); // '[object Promise]'

async/await 提供更好的錯誤堆棧跟蹤

V8工程師Mathias寫了一篇名為Asynchronous stack traces: why await beats Promise#then()? 的文章,介紹了為什么與 Promise相比,引擎更容易捕捉和存儲 async/await 的堆棧跟蹤。事例如下:

async function foo() {
await bar();
return 'value';
}

function bar() {
throw new Error('BEEP BEEP');
}

foo().catch((error) => console.log(error.stack));

// Error: BEEP BEEP
// at bar (<anonymous>:7:9)
// at foo (<anonymous>:2:9)
// at <anonymous>:10:1

async 版本正確地捕獲了錯誤堆棧跟蹤。

我們再來看看 Promise  版本。

function foo() {
return bar().then(() => 'value');
}

function bar() {
return Promise.resolve().then(() => {
throw new Error('BEEP BEEP');
});
}

foo().catch((error) => console.log(error.stack));

// Error: BEEP BEEP at <anonymous>:7:11

堆棧跟蹤丟失。從匿名的箭頭函數切換到命名的函數聲明有一點幫助,但幫助不大:

function foo() {
return bar().then(() => 'value');
}

function bar() {
return Promise.resolve().then(function thisWillThrow() {
throw new Error('BEEP BEEP');
});
}

foo().catch((error) => console.log(error.stack));

// Error: BEEP BEEP
// at thisWillThrow (<anonymous>:7:11)

對 async/await 常見反對意見

對 async/await 主要有兩種常見的反對意見。

首先,當獨立的異步函數調用可以用Promise.all?并發處理時,如果我們還大量使用async/await? 可能會導致濫用,這樣會造成開發者不去試圖了解 Promise 的幕后是如何工作,而只是一味的使用 async/await。

第二種情況更為微妙。一些函數式編程愛好者認為 async/await? 會招致命令式編程。從 FP 程序員的角度來看,能夠使用循環和 try catch 并不是一件好事,因為這些語言結構意味著副作用,并鼓勵使用不那么理想的錯誤處理。

我對這種說法待保留意見。FP程序員理所當然地關心他們程序中的確定性。他們希望對自己的代碼有絕對的信心。為了達到這個目的,需要一個復雜的類型系統,其中包括Result等類型。但我不認為async/await本身與FP不相容。

無論如何,對于大多數人來說,包括我在內,FP仍然是一種后天的味道(盡管我確實認為FP超級酷,而且我正在慢慢學習它)。async/await?提供的正常控制流語句和try catch錯誤處理,對于我們在 JavaScript 中協調復雜的異步操作是非常寶貴的。這正是為什么說 "async/await只是一種語法糖" 是一種輕描淡寫的說法。

作者:zhenghao  

譯者:前端小智

來源:zhenghao

原文:https://www.zhenghao.io/posts/await-vs-promise?

責任編輯:武曉燕 來源: 大遷世界
相關推薦

2020-01-15 06:00:52

物聯網IOT大數據

2013-07-04 15:22:46

華為WLAN接入

2009-10-19 10:50:20

內部云

2020-12-16 09:27:05

數據湖大數據數據

2013-12-18 12:45:59

2012-11-06 16:53:55

歐朋Opera瀏覽器

2015-12-01 14:26:57

2013-08-22 11:27:32

云服務云存儲

2022-10-11 16:35:34

加密貨幣區塊鏈代幣

2012-05-11 16:46:00

激光打印機推薦

2011-12-01 16:18:09

數據治理informatica數據集成

2020-08-24 19:00:20

國產操作系統操作系統

2019-07-18 15:21:40

Linux容器IT

2018-07-06 05:03:13

2016-04-11 09:18:22

OpenStack/華

2010-03-23 10:59:14

2020-01-16 08:20:44

數據隱私機密性數據安全

2019-01-09 09:13:40

2019-06-25 10:41:45

Redis緩存數據庫

2010-03-03 11:39:18

點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产亚洲精品久久久优势 | 91精品国产综合久久国产大片 | 黄色网址免费在线观看 | 日韩黄色免费 | 欧美jizzhd精品欧美巨大免费 | 日韩字幕 | av网站免费在线观看 | 欧美人妇做爰xxxⅹ性高电影 | 毛片在线看片 | 综合久 | 欧美一区二 | 美国av毛片 | 亚洲精品久久久久久国产精华液 | 在线播放亚洲 | 欧美乱操| 亚洲日本激情 | 欧美日韩成人网 | 成人福利电影 | 999久久久久久久久6666 | 国产91丝袜在线播放 | av永久免费 | 国户精品久久久久久久久久久不卡 | 欧美成人黄色小说 | 国产精品久久久久久久久久久免费看 | 久久黄色 | 精品国产色 | 日韩欧美国产成人一区二区 | 日日天天 | 在线国产欧美 | 中文精品一区二区 | 99re热精品视频国产免费 | 成人精品系列 | 中文字幕精品一区二区三区精品 | 羞羞视频网页 | www久久久| 日韩精品视频在线播放 | 欧美亚洲视频在线观看 | 日韩不卡一区二区 | 天堂中文资源在线 | 日韩有码一区 | 99精品视频免费观看 |