J'ai une question concernant l' Array.forEach
implémentation native de JavaScript: se comporte-t-il de manière asynchrone? Par exemple, si j'appelle:
[many many elements].forEach(function () {lots of work to do})
Sera-ce non bloquant?
J'ai une question concernant l' Array.forEach
implémentation native de JavaScript: se comporte-t-il de manière asynchrone? Par exemple, si j'appelle:
[many many elements].forEach(function () {lots of work to do})
Sera-ce non bloquant?
Réponses:
Non, c'est bloquant. Jetez un oeil à la spécification de l'algorithme .
Cependant, une implémentation peut-être plus facile à comprendre est donnée sur MDN :
Si vous devez exécuter beaucoup de code pour chaque élément, vous devriez envisager d'utiliser une approche différente:
puis appelez-le avec:
Ce serait alors non bloquant. L'exemple est tiré de JavaScript haute performance .
Une autre option pourrait être les travailleurs Web .
la source
forEach
par exemple, ne bloque pas lesawait
instructions et vous devriez plutôt utiliser unefor
boucle: stackoverflow.com/questions/37962880/…await
internesasync
. MaisforEach
ne sait pas ce que sont les fonctions asynchrones. Gardez à l'esprit que les fonctions asynchrones ne sont que des fonctions renvoyant une promesse. Vous attendriez-vousforEach
à gérer une promesse renvoyée par le rappel?forEach
ignore complètement la valeur de retour du rappel. Il ne pourrait gérer un rappel asynchrone que s'il était lui-même asynchrone.Si vous avez besoin d'une version conviviale
Array.forEach
et similaire de asynchrone , elles sont disponibles dans le module 'async' de Node.js: http://github.com/caolan/async ... en prime, ce module fonctionne également dans le navigateur .la source
eachSeries
place.Il existe un schéma commun pour effectuer un calcul très lourd dans Node qui peut vous être applicable ...
Le nœud est monothread (comme choix de conception délibéré, voir Qu'est - ce que Node.js? ); cela signifie qu'il ne peut utiliser qu'un seul cœur. Les boîtes modernes ont 8, 16 ou même plus de cœurs, ce qui pourrait laisser 90 +% de la machine inactive. Le modèle commun pour un service REST est de lancer un processus de nœud par cœur et de les placer derrière un équilibreur de charge local comme http://nginx.org/ .
Bifurquer un enfant - Pour ce que vous essayez de faire, il existe un autre schéma courant, bousculant un processus enfant pour faire le gros du travail. L'avantage est que le processus enfant peut effectuer des calculs lourds en arrière-plan tandis que votre processus parent est sensible à d'autres événements. Le hic, c'est que vous ne pouvez pas / ne devez pas partager la mémoire avec ce processus enfant (pas sans BEAUCOUP de contorsions et du code natif); vous devez passer des messages. Cela fonctionnera à merveille si la taille de vos données d'entrée et de sortie est petite par rapport au calcul qui doit être effectué. Vous pouvez même lancer un processus node.js enfant et utiliser le même code que vous utilisiez précédemment.
Par exemple:
la source
Array.forEach
est destiné à l'informatique qui n'attend pas, et il n'y a rien à gagner à faire des calculs asynchrones dans une boucle d'événement (les webworkers ajoutent le multiprocessing, si vous avez besoin d'un calcul multi-core). Si vous souhaitez attendre la fin de plusieurs tâches, utilisez un compteur que vous pouvez encapsuler dans une classe de sémaphore.la source
Edit 2018-10-11: Il semble qu'il y ait de fortes chances que la norme décrite ci-dessous ne passe pas, envisagez la canalisation comme alternative (ne se comporte pas exactement de la même manière mais des méthodes pourraient être mises en œuvre dans un manoir similaire).
C'est exactement pourquoi je suis enthousiasmé par es7, à l'avenir, vous pourrez faire quelque chose comme le code ci-dessous (certaines des spécifications ne sont pas complètes, utilisez-les donc avec prudence, je vais essayer de le garder à jour). Mais en gros, en utilisant l'opérateur new :: bind, vous pourrez exécuter une méthode sur un objet comme si le prototype de l'objet contenait la méthode. par exemple [Object] :: [Method] où normalement vous appelleriez [Object]. [ObjectsMethod]
Notez que pour ce faire aujourd'hui (24-juillet-16) et que cela fonctionne dans tous les navigateurs, vous devrez transpiler votre code pour les fonctionnalités suivantes: importation / exportation , fonctions fléchées , promesses , asynchrone / attente et surtout fonction bind . Le code ci-dessous pourrait être modifié pour n'utiliser que la fonction bind si nécessaire, toutes ces fonctionnalités sont parfaitement disponibles aujourd'hui en utilisant babel .
YourCode.js (où « beaucoup de travail à faire » doit simplement renvoyer une promesse, la résoudre lorsque le travail asynchrone est terminé.)
ArrayExtensions.js
la source
Il s'agit d'une fonction asynchrone courte à utiliser sans nécessiter de bibliothèques tierces
la source
Il y a un paquet sur npm pour une asynchrone facile pour chaque boucle .
Aussi une autre variante pour AllAsync
la source
Il est possible de coder même la solution comme celle-ci par exemple:
En revanche, il est beaucoup plus lent qu'un "pour".
Sinon, l'excellente bibliothèque Async peut le faire: https://caolan.github.io/async/docs.html#each
la source
Voici un petit exemple que vous pouvez exécuter pour le tester:
Cela produira quelque chose comme ça (si cela prend trop de temps / moins, augmentez / diminuez le nombre d'itérations):
la source
Utilisation Promise.each de Bluebird bibliothèque.
Cette méthode parcourt un tableau, ou une promesse d'un tableau, qui contient des promesses (ou un mélange de promesses et de valeurs) avec la fonction d' itérateur donnée avec la signature (valeur, index, longueur) où la valeur est la valeur résolue d'un promesse respective dans le tableau d'entrée. L'itération se produit en série. Si la fonction itérateur retourne une promesse ou un élément exploitable, le résultat de la promesse est attendu avant de continuer avec l'itération suivante. Si une promesse du tableau d'entrée est rejetée, la promesse retournée est également rejetée.
Si toutes les itérations se résolvent avec succès, Promise.each résout le tableau d'origine non modifié . Cependant, si une itération rejette ou fait une erreur, Promise.each cesse immédiatement son exécution et ne traite aucune autre itération. L'erreur ou la valeur rejetée est retournée dans ce cas au lieu du tableau d'origine.
Cette méthode est destinée à être utilisée pour les effets secondaires.
la source