最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文帶你了解async/await的使用

 更新時(shí)間:2022年09月01日 14:05:34   作者:前端小智  
async/await?讓異步代碼變成同步的方式,從而使代碼更具表現(xiàn)力和可讀性;還統(tǒng)一了異步編程的經(jīng)驗(yàn);以及提供了更好的錯(cuò)誤堆棧跟蹤。本文就來(lái)講講async/await的使用,需要的可以參考一下

開篇觀點(diǎn),async/await 不僅僅是 Promise 上面的語(yǔ)法糖,因?yàn)?async/await 確實(shí)提供了切實(shí)的好處。

  • async/await 讓異步代碼變成同步的方式,從而使代碼更具表現(xiàn)力和可讀性。
  • async/await 統(tǒng)一了異步編程的經(jīng)驗(yàn);以及提供了更好的錯(cuò)誤堆棧跟蹤。

關(guān)于 JS 中異步編程的一點(diǎn)歷史

異步編程在 JavaScript 中很常見(jiàn)。每當(dāng)我們需要進(jìn)行網(wǎng)絡(luò)服務(wù)調(diào)用、文件訪問(wèn)或數(shù)據(jù)庫(kù)操作時(shí),盡管語(yǔ)言是單線程的,但異步性是我們防止用戶界面被阻塞的方法。

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

Es6 中引入了 Promise,它是一個(gè)用于異步操作的一流對(duì)象,我們可以輕松地傳遞、組合、聚合和應(yīng)用轉(zhuǎn)換。時(shí)間上的依賴性通過(guò) then方法鏈干凈地表達(dá)出來(lái)。

有了 Promise 這個(gè)強(qiáng)大的伙伴,聽起來(lái)異步編程在 JS 中是一個(gè)已經(jīng)解決的問(wèn)題,對(duì)嗎?

恩,還沒(méi)有,因?yàn)橛袝r(shí)候 Promise 的級(jí)別太低了,不太適合使用。

有時(shí) Promise 的級(jí)別太低,不適合使用

盡管出現(xiàn)了 Promise,但在 JS 中仍然需要一個(gè)更高級(jí)別的語(yǔ)言結(jié)構(gòu)來(lái)進(jìn)行異步編程。

我們來(lái)看個(gè)例子, 假設(shè)我們需要某個(gè)函數(shù)在某個(gè)時(shí)間間隔輪詢一個(gè)API。當(dāng)達(dá)到最大重試次數(shù)時(shí),它就會(huì)解析為 null

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

let count = 0;

function apiCall() {
  return new Promise((resolve) =>
    // a在第6次重試時(shí),它被解析為 "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) => {
    // 為了簡(jiǎn)潔起見(jiàn),跳過(guò)錯(cuò)誤處理

    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'

這種解決方案的直觀性和可讀性取決于人們對(duì)Promise的熟悉程度,以及 Promise.resolve 如何 "平鋪" Promise 和遞歸。對(duì)我來(lái)說(shuō),這不是寫這樣一個(gè)函數(shù)的最可讀的方式。

使用 async/await

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

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

我想大多數(shù)人都會(huì)覺(jué)得上面的解決方案更有可讀性,因?yàn)槲覀兡軌蚴褂盟姓5恼Z(yǔ)言結(jié)構(gòu),如循環(huán)、異步操作的 try-catch 等。

這可能是 async/await 的最大賣點(diǎn)--使我們能夠以同步的方式編寫異步代碼。另一方面,這可能是對(duì) async/await 最常見(jiàn)的反對(duì)意見(jiàn)的來(lái)源,稍后再談這個(gè)問(wèn)題。

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

async/await 在同步和異步代碼中提供了統(tǒng)一的體驗(yàn)

async/await的另一個(gè)好處是,await自動(dòng)將任何非Promise(non-thenables)包裝成 Promises 。await的語(yǔ)義等同于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 返回的數(shù)字 1 上,就會(huì)出現(xiàn)以下錯(cuò)誤。

function fetchValue() {
  return 1;
}

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

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

最后, 從 async 函數(shù)返回的任何東西都是一個(gè) Promise:

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

async/await 提供更好的錯(cuò)誤堆棧跟蹤

V8工程師Mathias寫了一篇名為Asynchronous stack traces: why await beats Promise#then() 的文章,介紹了為什么與 Promise相比,引擎更容易捕捉和存儲(chǔ) 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 版本正確地捕獲了錯(cuò)誤堆棧跟蹤。

我們?cè)賮?lái)看看 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

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

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)

對(duì) async/await 常見(jiàn)反對(duì)意見(jiàn)

對(duì) async/await 主要有兩種常見(jiàn)的反對(duì)意見(jiàn)。

首先,當(dāng)獨(dú)立的異步函數(shù)調(diào)用可以用Promise.all并發(fā)處理時(shí),如果我們還大量使用async/await 可能會(huì)導(dǎo)致濫用,這樣會(huì)造成開發(fā)者不去試圖了解 Promise 的幕后是如何工作,而只是一味的使用 async/await。

第二種情況更為微妙。一些函數(shù)式編程愛(ài)好者認(rèn)為 async/await 會(huì)招致命令式編程。從 FP 程序員的角度來(lái)看,能夠使用循環(huán)和 try catch 并不是一件好事,因?yàn)檫@些語(yǔ)言結(jié)構(gòu)意味著副作用,并鼓勵(lì)使用不那么理想的錯(cuò)誤處理。

我對(duì)這種說(shuō)法待保留意見(jiàn)。FP程序員理所當(dāng)然地關(guān)心他們程序中的確定性。他們希望對(duì)自己的代碼有絕對(duì)的信心。為了達(dá)到這個(gè)目的,需要一個(gè)復(fù)雜的類型系統(tǒng),其中包括Result等類型。但我不認(rèn)為async/await本身與FP不相容。

無(wú)論如何,對(duì)于大多數(shù)人來(lái)說(shuō),包括我在內(nèi),F(xiàn)P仍然是一種后天的味道(盡管我確實(shí)認(rèn)為FP超級(jí)酷,而且我正在慢慢學(xué)習(xí)它)。async/await提供的正??刂屏髡Z(yǔ)句和try catch錯(cuò)誤處理,對(duì)于我們?cè)?JavaScript 中協(xié)調(diào)復(fù)雜的異步操作是非常寶貴的。這正是為什么說(shuō) "async/await只是一種語(yǔ)法糖" 是一種輕描淡寫的說(shuō)法。

以上就是一文帶你了解async/await的使用的詳細(xì)內(nèi)容,更多關(guān)于async/await的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • 讓JavaScript的Alert彈出框失效的方法禁止彈出警告框

    讓JavaScript的Alert彈出框失效的方法禁止彈出警告框

    彈出框難免會(huì)影響你的心情,所以通過(guò)以下代碼可將Js彈出框屏蔽掉,實(shí)現(xiàn)思路是對(duì)alert方法重寫
    2014-09-09
  • Bootstrap每天必學(xué)之導(dǎo)航條

    Bootstrap每天必學(xué)之導(dǎo)航條

    Bootstrap每天必學(xué)之導(dǎo)航條,本文向大家講解了多種多樣的導(dǎo)航條,以及導(dǎo)航條中元素的實(shí)現(xiàn)方法,感興趣的小伙伴們可以參考一下
    2015-11-11
  • echarts實(shí)現(xiàn)晶體球面投影的實(shí)例教程

    echarts實(shí)現(xiàn)晶體球面投影的實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于echarts實(shí)現(xiàn)晶體球面投影的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-10-10
  • BootStrap table刪除指定行的注意事項(xiàng)(筆記整理)

    BootStrap table刪除指定行的注意事項(xiàng)(筆記整理)

    在前端開發(fā)中遇到這樣的問(wèn)題,對(duì)于table指定行的數(shù)據(jù)進(jìn)行刪除,花了好長(zhǎng)時(shí)間才解決,今天小編抽時(shí)間給大家介紹BootStrap table刪除指定行的注意事項(xiàng),需要的朋友參考下吧
    2017-02-02
  • JavaScript操作元素實(shí)例大全

    JavaScript操作元素實(shí)例大全

    JavaScript可以對(duì)各種網(wǎng)頁(yè)元素進(jìn)行操控,下面這篇文章主要給大家介紹了關(guān)于JavaScript操作元素的相關(guān)資料,文中通過(guò)多個(gè)實(shí)例詳細(xì)介紹了操作元素的方法,需要的朋友可以參考下
    2021-06-06
  • JavaScript幾種彈窗事件的使用

    JavaScript幾種彈窗事件的使用

    這篇文章主要介紹了JavaScript幾種彈窗事件的使用,彈窗事件就是在我們執(zhí)行某操作的時(shí)候,彈出信息框給出提示?;蚴占瘮?shù)據(jù)的時(shí)候,彈出窗口收集信息,不想收集可以取消隱藏,下文介紹需要的朋友可以參考一下
    2022-02-02
  • ES6入門教程之Class和Module詳解

    ES6入門教程之Class和Module詳解

    這篇文章主要給大家介紹了ES6中Class和Module的相關(guān)資料,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-05-05
  • Javascript 函數(shù)對(duì)象的多重身份

    Javascript 函數(shù)對(duì)象的多重身份

    函數(shù)對(duì)象是javascript 中一個(gè)很特殊的對(duì)象,其特殊體現(xiàn)在他的多重身份上。
    2009-06-06
  • JS實(shí)現(xiàn)動(dòng)態(tài)修改table及合并單元格的方法示例

    JS實(shí)現(xiàn)動(dòng)態(tài)修改table及合并單元格的方法示例

    這篇文章主要介紹了JS實(shí)現(xiàn)動(dòng)態(tài)修改table及合并單元格的方法,結(jié)合完整實(shí)例形式分析了JS動(dòng)態(tài)遍歷及修改table單元格的具體操作技巧,需要的朋友可以參考下
    2017-02-02
  • 一文詳解如何使npm-scripts更好維護(hù)的配置方法

    一文詳解如何使npm-scripts更好維護(hù)的配置方法

    這篇文章主要為大家介紹了如何使npm-scripts更好維護(hù)的配置方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06

最新評(píng)論

庆元县| 内黄县| 达尔| 武强县| 社会| 芮城县| 满洲里市| 龙江县| 新安县| 洪江市| 勃利县| 常州市| 扎赉特旗| 南漳县| 西乌珠穆沁旗| 涞水县| 随州市| 德州市| 清丰县| 丰宁| 盐边县| 天台县| 清原| 乌鲁木齐县| 铜陵市| 伊川县| 徐闻县| 鹿泉市| 阿克陶县| 文成县| 舞钢市| 科技| 玉龙| 栾川县| 庄河市| 峨边| 莎车县| 云林县| 青冈县| 石渠县| 桐城市|