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

資訊專欄INFORMATION COLUMN

如何在 JS 循環(huán)中正確使用 async 與 await

liujs / 1738人閱讀

摘要:蛤當(dāng)你嘗試在循環(huán)中使用時(shí),事情就會(huì)變得復(fù)雜一些。這意味著循環(huán)中的應(yīng)該按順序執(zhí)行。在循環(huán)中使用首先,使用對(duì)數(shù)組進(jìn)行遍歷。在中使用如果在中使用始終返回?cái)?shù)組,這是因?yàn)楫惒胶瘮?shù)總是返回。在循環(huán)中使用當(dāng)你使用時(shí),希望篩選具有特定結(jié)果的數(shù)組。

asyncawait 的使用方式相對(duì)簡(jiǎn)單。 蛤當(dāng)你嘗試在循環(huán)中使用await時(shí),事情就會(huì)變得復(fù)雜一些。

想閱讀更多優(yōu)質(zhì)文章請(qǐng)猛戳GitHub博客,一年百來篇優(yōu)質(zhì)文章等著你!

在本文中,分享一些在如果循環(huán)中使用await值得注意的問題。

準(zhǔn)備一個(gè)例子

對(duì)于這篇文章,假設(shè)你想從水果籃中獲取水果的數(shù)量。

const fruitBasket = {
 apple: 27,
 grape: 0,
 pear: 14
};

你想從fruitBasket獲得每個(gè)水果的數(shù)量。 要獲取水果的數(shù)量,可以使用getNumFruit函數(shù)。

const getNumFruit = fruit => {
  return fruitBasket[fruit];
};

const numApples = getNumFruit("apple");
console.log(numApples); //27

現(xiàn)在,假設(shè)fruitBasket是從服務(wù)器上獲取,這里我們使用 setTimeout 來模擬。

const sleep = ms => {
  return new Promise(resolve => setTimeout(resolve, ms))
};

const getNumFruie = fruit => {
  return sleep(1000).then(v => fruitBasket[fruit]);
};

getNumFruit("apple").then(num => console.log(num)); // 27

最后,假設(shè)你想使用awaitgetNumFruit來獲取異步函數(shù)中每個(gè)水果的數(shù)量。

const control = async _ => {
  console.log("Start")

  const numApples = await getNumFruit("apple");
  console.log(numApples);

  const numGrapes = await getNumFruit("grape");
  console.log(numGrapes);

  const numPears = await getNumFruit("pear");
  console.log(numPears);

  console.log("End")
}

在 for 循環(huán)中使用 await

首先定義一個(gè)存放水果的數(shù)組:

const fruitsToGet = [“apple”, “grape”, “pear”];

循環(huán)遍歷這個(gè)數(shù)組:

const forLoop = async _ => {
  console.log("Start");
  
  for (let index = 0; index < fruitsToGet.length; index++) {
    // 得到每個(gè)水果的數(shù)量
  }

  console.log("End")
}

for循環(huán)中,過上使用getNumFruit來獲取每個(gè)水果的數(shù)量,并將數(shù)量打印到控制臺(tái)。

由于getNumFruit返回一個(gè)promise,我們使用 await 來等待結(jié)果的返回并打印它。

const forLoop = async _ => {
  console.log("start");

  for (let index = 0; index < fruitsToGet.length; index ++) {
    const fruit = fruitsToGet[index];
    const numFruit = await getNumFruit(fruit);
    console.log(numFruit);
  }
  console.log("End")
}

當(dāng)使用await時(shí),希望JavaScript暫停執(zhí)行,直到等待 promise 返回處理結(jié)果。這意味著for循環(huán)中的await 應(yīng)該按順序執(zhí)行。

結(jié)果正如你所預(yù)料的那樣。

“Start”;
“Apple: 27”;
“Grape: 0”;
“Pear: 14”;
“End”;

這種行為適用于大多數(shù)循環(huán)(比如whilefor-of循環(huán))…

但是它不能處理需要回調(diào)的循環(huán),如forEachmapfilterreduce。在接下來的幾節(jié)中,我們將研究await 如何影響forEach、map和filter

在 forEach 循環(huán)中使用 await

首先,使用 forEach 對(duì)數(shù)組進(jìn)行遍歷。

const forEach = _ => {
  console.log("start");

  fruitsToGet.forEach(fruit => {
    //...
  })

  console.log("End")
}

接下來,我們將嘗試使用getNumFruit獲取水果數(shù)量。 (注意回調(diào)函數(shù)中的async關(guān)鍵字。我們需要這個(gè)async關(guān)鍵字,因?yàn)?b>await在回調(diào)函數(shù)中)。

const forEachLoop = _ => {
  console.log("Start");

  fruitsToGet.forEach(async fruit => {
    const numFruit = await getNumFruit(fruit);
    console.log(numFruit)
  });

  console.log("End")
}

我期望控制臺(tái)打印以下內(nèi)容:

“Start”;
“27”;
“0”;
“14”;
“End”;

但實(shí)際結(jié)果是不同的。在forEach循環(huán)中等待返回結(jié)果之前,JavaScrip先執(zhí)行了 console.log("End")。

實(shí)際控制臺(tái)打印如下:

‘Start’
‘End’
‘27’
‘0’
‘14’

JavaScript 中的 forEach不支持 promise 感知,也支持 asyncawait,所以不能在 forEach 使用 await

在 map 中使用 await

如果在map中使用await, map 始終返回promise數(shù)組,這是因?yàn)楫惒胶瘮?shù)總是返回promise

const mapLoop = async _ => {
  console.log("Start")
  const numFruits = await fruitsToGet.map(async fruit => {
    const numFruit = await getNumFruit(fruit);
    return numFruit;
  })
  
  console.log(numFruits);

  console.log("End")
}
      

“Start”;
“[Promise, Promise, Promise]”;
“End”;

如果你在 map 中使用 awaitmap 總是返回promises,你必須等待promises 數(shù)組得到處理。 或者通過await Promise.all(arrayOfPromises)來完成此操作。


const mapLoop = async _ => {
  console.log("Start");

  const promises = fruitsToGet.map(async fruit => {
    const numFruit = await getNumFruit(fruit);
    return numFruit;
  });

  const numFruits = await Promise.all(promises);
  console.log(numFruits);

  console.log("End")
}

運(yùn)行結(jié)果如下:

如果你愿意,可以在promise 中處理返回值,解析后的將是返回的值。

const mapLoop = _ => {
  // ...
  const promises = fruitsToGet.map(async fruit => {
    const numFruit = await getNumFruit(fruit);
    return numFruit + 100
  })
  // ...
}
 
“Start”;
“[127, 100, 114]”;
“End”;


在 filter 循環(huán)中使用 await

當(dāng)你使用filter時(shí),希望篩選具有特定結(jié)果的數(shù)組。假設(shè)過濾數(shù)量大于20的數(shù)組。

如果你正常使用filter (沒有 await),如下:

const filterLoop =  _ => {
  console.log("Start")

  const moreThan20 =  fruitsToGet.filter(async fruit => {
    const numFruit = await fruitBasket[fruit]
    return numFruit > 20
  })
  
  console.log(moreThan20) 
  console.log("END")
}

運(yùn)行結(jié)果

Start
["apple"]
END

filter 中的await不會(huì)以相同的方式工作。 事實(shí)上,它根本不起作用。

const filterLoop = async _ => {
  console.log("Start")

  const moreThan20 =  await fruitsToGet.filter(async fruit => {
    const numFruit = fruitBasket[fruit]
    return numFruit > 20
  })
  
  console.log(moreThan20) 
  console.log("END")
}


// 打印結(jié)果
Start
["apple", "grape", "pear"]
END
 

為什么會(huì)發(fā)生這種情況?

當(dāng)在filter 回調(diào)中使用await時(shí),回調(diào)總是一個(gè)promise。由于promise 總是真的,數(shù)組中的所有項(xiàng)都通過filter 。在filter 使用 await類以下這段代碼

const filtered = array.filter(true);

filter使用 await 正確的三個(gè)步驟

使用map返回一個(gè)promise 數(shù)組

使用 await 等待處理結(jié)果

使用 filter 對(duì)返回的結(jié)果進(jìn)行處理

const filterLoop = async _ => {
  console.log("Start");

  const promises = await fruitsToGet.map(fruit => getNumFruit(fruit));
 
  const numFruits = await Promise.all(promises);

  const moreThan20 = fruitsToGet.filter((fruit, index) => {
    const numFruit = numFruits[index];
    return numFruit > 20;
  })

  console.log(moreThan20);
  console.log("End")
} 

在 reduce 循環(huán)中使用 await

如果想要計(jì)算 fruitBastet中的水果總數(shù)。 通常,你可以使用reduce循環(huán)遍歷數(shù)組并將數(shù)字相加。

const reduceLoop = _ => {
  console.log("Start");

  const sum = fruitsToGet.reduce((sum, fruit) => {
    const numFruit = fruitBasket[fruit];
    return sum + numFruit;
  }, 0)

  console.log(sum)
  console.log("End")
}
 

運(yùn)行結(jié)果:

當(dāng)你在 reduce 中使用await時(shí),結(jié)果會(huì)變得非常混亂。

 const reduceLoop = async _ => {
  console.log("Start");

  const sum = await fruitsToGet.reduce(async (sum, fruit) => {
    const numFruit = await fruitBasket[fruit];
    return sum + numFruit;
  }, 0)

  console.log(sum)
  console.log("End")
}
 

[object Promise]14 是什么 鬼??

剖析這一點(diǎn)很有趣。

在第一次遍歷中,sum0numFruit27(通過getNumFruit(apple)的得到的值),0 + 27 = 27

在第二次遍歷中,sum是一個(gè)promise。 (為什么?因?yàn)楫惒胶瘮?shù)總是返回promises!)numFruit0.promise 無法正常添加到對(duì)象,因此JavaScript將其轉(zhuǎn)換為[object Promise]字符串。 [object Promise] + 0object Promise] 0

在第三次遍歷中,sum 也是一個(gè)promisenumFruit14. [object Promise] + 14[object Promise] 14

解開謎團(tuán)!

這意味著,你可以在reduce回調(diào)中使用await,但是你必須記住先等待累加器!

const reduceLoop = async _ => {
  console.log("Start");

  const sum = await fruitsToGet.reduce(async (promisedSum, fruit) => {
    const sum = await promisedSum;
    const numFruit = await fruitBasket[fruit];
    return sum + numFruit;
  }, 0)

  console.log(sum)
  console.log("End")
}

但是從上圖中看到的那樣,await 操作都需要很長(zhǎng)時(shí)間。 發(fā)生這種情況是因?yàn)?b>reduceLoop需要等待每次遍歷完成promisedSum

有一種方法可以加速reduce循環(huán),如果你在等待promisedSum之前先等待getNumFruits(),那么reduceLoop只需要一秒鐘即可完成:

const reduceLoop = async _ => {
  console.log("Start");

  const sum = await fruitsToGet.reduce(async (promisedSum, fruit) => {
    const numFruit = await fruitBasket[fruit];
    const sum = await promisedSum;
    return sum + numFruit;
  }, 0)

  console.log(sum)
  console.log("End")
}

這是因?yàn)?b>reduce可以在等待循環(huán)的下一個(gè)迭代之前觸發(fā)所有三個(gè)getNumFruit promise。然而,這個(gè)方法有點(diǎn)令人困惑,因?yàn)槟惚仨氉⒁獾却捻樞颉?/p>

在reduce中使用wait最簡(jiǎn)單(也是最有效)的方法是

使用map返回一個(gè)promise 數(shù)組

使用 await 等待處理結(jié)果

使用 reduce 對(duì)返回的結(jié)果進(jìn)行處理

const reduceLoop = async _ => {
console.log("Start");

const promises = fruitsToGet.map(getNumFruit);
const numFruits = await Promise.all(promises);
const sum = numFruits.reduce((sum, fruit) => sum + fruit);

console.log(sum)
console.log("End")
}

這個(gè)版本易于閱讀和理解,需要一秒鐘來計(jì)算水果總數(shù)。

從上面看出來什么

如果你想連續(xù)執(zhí)行await調(diào)用,請(qǐng)使用for循環(huán)(或任何沒有回調(diào)的循環(huán))。

永遠(yuǎn)不要和forEach一起使用await,而是使用for循環(huán)(或任何沒有回調(diào)的循環(huán))。

不要在 filterreduce 中使用 await,如果需要,先用 map 進(jìn)一步驟處理,然后在使用 filterreduce 進(jìn)行處理。

交流

干貨系列文章匯總?cè)缦拢X得不錯(cuò)點(diǎn)個(gè)Star,歡迎 加群 互相學(xué)習(xí)。

https://github.com/qq44924588...

我是小智,公眾號(hào)「大遷世界」作者,對(duì)前端技術(shù)保持學(xué)習(xí)愛好者。我會(huì)經(jīng)常分享自己所學(xué)所看的干貨,在進(jìn)階的路上,共勉!

關(guān)注公眾號(hào),后臺(tái)回復(fù)福利,即可看到福利,你懂的。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/104421.html

相關(guān)文章

  • JavaScript是如何工作的:事件循環(huán)和異步編程的崛起+ 5種使用 async/await

    摘要:事件循環(huán)從回調(diào)隊(duì)列中獲取并將其推入調(diào)用堆棧。執(zhí)行從調(diào)用堆棧中移除從調(diào)用堆棧中移除快速回顧值得注意的是,指定了事件循環(huán)應(yīng)該如何工作,這意味著在技術(shù)上它屬于引擎的職責(zé)范圍,不再僅僅扮演宿主環(huán)境的角色。 此篇是 JavaScript是如何工作的第四篇,其它三篇可以看這里: JavaScript是如何工作的:引擎,運(yùn)行時(shí)和調(diào)用堆棧的概述! JavaScript是如何工作的:深入V8引擎&編寫...

    Honwhy 評(píng)論0 收藏0
  • JavaScript工作原理(四):事件循環(huán),異步編程的興起以及5招async/await實(shí)踐

    摘要:事件循環(huán)從回調(diào)隊(duì)列中獲取并將其推送到調(diào)用堆棧。如何工作請(qǐng)注意,不會(huì)自動(dòng)將您的回調(diào)函數(shù)放到事件循環(huán)隊(duì)列中。它設(shè)置了一個(gè)計(jì)時(shí)器,當(dāng)計(jì)時(shí)器到期時(shí),環(huán)境將您的回調(diào)函數(shù)放入事件循環(huán)中,以便將來的某個(gè)事件會(huì)將其選中并執(zhí)行它。 我們將通過回顧第一篇文章中單線程編程的缺點(diǎn),然后在討論如何克服它們來構(gòu)建令人驚嘆的JavaScript UI。在文章結(jié)尾處,我們將分享5個(gè)關(guān)于如何使用async / awai...

    piglei 評(píng)論0 收藏0
  • ES6—Async異步編程(11)

    摘要:所以異步編程對(duì)語(yǔ)言太重要。異步編程我們就以用戶注冊(cè)這個(gè)特別常見的場(chǎng)景為例,講講異步編程。這種層層嵌套被稱為回調(diào)地獄。相比回調(diào)函數(shù)而言,代碼可讀性更高,代碼的執(zhí)行順序一目了然。函數(shù)內(nèi)部語(yǔ)句返回的值,會(huì)成為方法回調(diào)函數(shù)的參數(shù)。 單線程是Javascript語(yǔ)言最本質(zhì)的特性之一,Javascript引擎在運(yùn)行js代碼的時(shí)候,同一個(gè)時(shí)間只能執(zhí)行單個(gè)任務(wù)。 這種模式的好處是實(shí)現(xiàn)起來比較簡(jiǎn)單,執(zhí)行...

    chengjianhua 評(píng)論0 收藏0
  • JavaScript 工作原理之四-事件循環(huán)及異步編程的出現(xiàn)和 5 種更好的 async/await

    摘要:函數(shù)會(huì)在之后的某個(gè)時(shí)刻觸發(fā)事件定時(shí)器。事件循環(huán)中的這樣一次遍歷被稱為一個(gè)。執(zhí)行完畢并出棧。當(dāng)定時(shí)器過期,宿主環(huán)境會(huì)把回調(diào)函數(shù)添加至事件循環(huán)隊(duì)列中,然后,在未來的某個(gè)取出并執(zhí)行該事件。 原文請(qǐng)查閱這里,略有改動(dòng)。 本系列持續(xù)更新中,Github 地址請(qǐng)查閱這里。 這是 JavaScript 工作原理的第四章。 現(xiàn)在,我們將會(huì)通過回顧單線程環(huán)境下編程的弊端及如何克服這些困難以創(chuàng)建令人驚嘆...

    maochunguang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<