Maison> interface Web> js tutoriel> le corps du texte

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

青灯夜游
Libérer: 2020-11-30 18:16:11
avant
4917 Les gens l'ont consulté

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

asyncetawaitsont relativement simples à utiliser. Mais les choses deviennent un peu plus compliquées lorsque vous essayez d'utiliserawaitdans une boucle.

Dans cet article, partagez quelques problèmes à noter lors de l'utilisation deawaitdans des boucles if.

Préparez un exemple

Pour cet article, disons que vous souhaitez obtenir le nombre de fruits d'une corbeille de fruits.

const fruitBasket = { apple: 27, grape: 0, pear: 14 };
Copier après la connexion

Vous souhaitez obtenir la quantité de chaque fruit defruitBasket. Pour obtenir le nombre de fruits, vous pouvez utiliser la fonctiongetNumFruit.

const getNumFruit = fruit => { return fruitBasket[fruit]; }; const numApples = getNumFruit('apple'); console.log(numApples); //27
Copier après la connexion

Maintenant, en supposant quefruitBasketsoit obtenu du serveur, nous utilisons icisetTimeoutpour simuler.

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
Copier après la connexion

Enfin, disons que vous souhaitez utiliserawaitetgetNumFruitpour obtenir la quantité de chaque fruit dans une fonction asynchrone.

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') }
Copier après la connexion

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

Utilisez wait

dans la boucle for Définissez d'abord un tableau pour stocker les fruits :

const fruitsToGet = [“apple”, “grape”, “pear”];
Copier après la connexion

. loop Parcourez ce tableau :

const forLoop = async _ => { console.log('Start'); for (let index = 0; index 

Dans la boucle for, utilisez getNumFruit pour obtenir le numéro de chaque fruit et imprimez le numéro sur la console.

Puisque getNumFruit renvoie un promise, nous utilisons await pour attendre que le résultat revienne et l'imprime.

const forLoop = async _ => { console.log('start'); for (let index = 0; index 

Lorsque vous utilisez await, vous souhaitez que JavaScript suspende l'exécution jusqu'à ce qu'il attende le retour de la promesse. Cela signifie que le for dans la boucle await doit être exécuté séquentiellement.

Les résultats sont tels que vous vous en doutez.

“Start”; “Apple: 27”; “Grape: 0”; “Pear: 14”; “End”;
Copier après la connexion

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

Ce comportement fonctionne pour la plupart des boucles (comme les boucleswhileetfor-of)...

mais il ne gère pas les boucles qui nécessitent des rappels, tels queforEach,map,filteretreduce. Dans les prochaines sections, nous verrons commentawaitaffecteforEach, la carte etfilter.

Utilisez wait

dans la boucle forEach Tout d'abord, utilisezforEachpour parcourir le tableau.

const forEach = _ => { console.log('start'); fruitsToGet.forEach(fruit => { //... }) console.log('End') }
Copier après la connexion

Ensuite, nous essaierons d'utilisergetNumFruitpour obtenir le nombre de fruits. (Notez le mot-cléasyncdans la fonction de rappel. Nous avons besoin de ce mot-cléasynccarawaitest dans la fonction de rappel).

const forEachLoop = _ => { console.log('Start'); fruitsToGet.forEach(async fruit => { const numFruit = await getNumFruit(fruit); console.log(numFruit) }); console.log('End') }
Copier après la connexion

Je m'attendais à ce que la console affiche ce qui suit :

“Start”; “27”; “0”; “14”; “End”;
Copier après la connexion

Mais le résultat réel est différent. Avant d'attendre que le résultat soit renvoyé dans la boucleforEach, JavaScript exécute d'abord console.log('End').

L'impression réelle de la console est la suivante :

‘Start’ ‘End’ ‘27’ ‘0’ ‘14’
Copier après la connexion

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

forEachen JavaScript ne prend pas en charge la sensibilisation aux promesses, mais prend également en chargeasyncetawait, donc impossible d'utiliserforEachà l'intérieur deawait.

Utilisez wait

dans la carte Si vous utilisezmapdansawait,maprenvoie toujours le tableaupromiseC'est à cause des fonctions asynchrones. toujours Oui renvoiepromise.

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”;
Copier après la connexion

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

Si vous utilisezmapà l'intérieur deawait,maprenvoie toujourspromiseset vous devez attendre que le tableaupromisessoit traité. Ou faites-le viaawait 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') }
Copier après la connexion

Le résultat d'exécution est le suivant :

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

Si vous le souhaitez, vous pouvez traiter la valeur de retour danspromise, et la valeur analysée sera la valeur renvoyée.

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

Utiliser wait

dans la boucle de filtre Lorsque vous utilisezfilter, vous souhaitez filtrer le tableau avec des résultats spécifiques. Supposons que vous filtrez un tableau dont le nombre est supérieur à 20.

Si vous utilisezfilternormalement (sans attendre), comme suit :

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') }
Copier après la connexion

Le résultat de l'exécution de

Start ["apple"] END
Copier après la connexion

filterne sera pas de la même manière. En fait, ça ne marche pas du tout.await

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') } // 打印结果 Start ["apple", "grape", "pear"] END
Copier après la connexion

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

Pourquoi cela se produit-il

Lorsque vous utilisez

dans un rappelfilter, le rappel est toujours unawait. Puisquepromiseest toujours vrai, tous les éléments du tableau passent parpromise. Utilisez le code suivant dansfilteren utilisant lafilterclasseawait

const filtered = array.filter(true);
Copier après la connexion

filter使用await正确的三个步骤

  1. 使用map返回一个promise 数组
  2. 使用await等待处理结果
  3. 使用filter对返回的结果进行处理
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') }
Copier après la connexion

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

在 reduce 循环中使用 await

如果想要计算fruitBastet中的水果总数。 通常,你可以使用reduce循环遍历数组并将数字相加。

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') }
Copier après la connexion

运行结果:

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

当你在reduce中使用await时,结果会变得非常混乱。

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') }
Copier après la connexion

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

[object Promise]14是什么 鬼??

剖析这一点很有趣。

  1. 在第一次遍历中,sum0numFruit27(通过getNumFruit(apple)的得到的值),0 + 27 = 27
  2. 在第二次遍历中,sum是一个promise。 (为什么?因为异步函数总是返回promises!)numFruit0.promise 无法正常添加到对象,因此JavaScript将其转换为[object Promise]字符串。[object Promise] + 0object Promise] 0
  3. 在第三次遍历中,sum也是一个promisenumFruit14.[object Promise] + 14[object Promise] 14

解开谜团!

这意味着,你可以在reduce回调中使用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') }
Copier après la connexion

Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

但是从上图中看到的那样,await操作都需要很长时间。 发生这种情况是因为reduceLoop需要等待每次遍历完成promisedSum

有一种方法可以加速reduce循环,如果你在等待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') }
Copier après la connexion

1Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

这是因为reduce可以在等待循环的下一个迭代之前触发所有三个getNumFruitpromise。然而,这个方法有点令人困惑,因为你必须注意等待的顺序。

在reduce中使用wait最简单(也是最有效)的方法是

  1. 使用map返回一个promise 数组
  2. 使用await等待处理结果
  3. 使用reduce对返回的结果进行处理

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

这个版本易于阅读和理解,需要一秒钟来计算水果总数。

1Comment utiliser async/await dans les boucles JavaScript ? A quoi dois-je faire attention ?

从上面看出来什么

  1. 如果你想连续执行await调用,请使用for循环(或任何没有回调的循环)。
  2. 永远不要和forEach一起使用await,而是使用for循环(或任何没有回调的循环)。
  3. 不要在filterreduce中使用await,如果需要,先用map进一步骤处理,然后在使用filterreduce进行处理。

原文地址:https://medium.com/free-code-camp/javascript-async-and-await-in-loops-30ecc5fb3939

更多编程相关知识,请访问:编程学习网站!!

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:segmentfault.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!