Quelle version d'async utilises-tu ?
3.1.0
Dans quel environnement le problème s'est-il produit (version du nœud/version du navigateur)
nœud 12.9.1, npm 6.10.2, navigateur N/A
Qu'est-ce que tu as fait?
Le problème a un thread dans stackoverflow
https://stackoverflow.com/questions/57622495/async-maplimit-with-promise/57659221#57659221
En gros, j'ai ce code :
async = require('async');
let numPromise = async.mapLimit(['1','2','3','4','5'], 3, function(num, callback){
setTimeout(function(){
num = num * 2,
console.log(num);
callback(null, num);
},
2000);
})
numPromise
.then((result) => console.log("success:" + result))
.catch(() => console.log("no success"));
Que vous attendiez-vous à ce qu'il se passe ?
Exécutez sans erreur, 'numPromise' doit contenir une promesse. la console devrait enregistrer '2,4,6,8,10' et ' success:2 ,4,6,8,10'
Quel a été le résultat réel ?
Il renvoie une erreur : TypeError : Impossible de lire la propriété 'alors' d' undefined
Remarque : lorsque j'utilise le module 'promise-async' au lieu de 'async', ce code fonctionne bien. La documentation indique qu'async.mapLimit (et d'autres) renvoient une promesse lorsqu'aucun rappel n'est fourni, mais je ne suis pas défini. Je n'ai pas encore trouvé d'échantillon fonctionnel (veuillez également consulter ma suggestion sur le problème « besoin d'échantillons »).
const async = require('async');
const delay = require('util').promisify(setTimeout);
const numPromise = async.mapLimit(['1','2','3','4','5'], 3, async num => delay(200).then(() => num*2))
// or const numPromise = async.mapLimit(['1','2','3','4','5'], 3, async num => {
// await delay(200);
// return num*2;
// })
numPromise.then(console.log)
Merci beaucoup, exemple raisonnable. Malheureusement, me donne "SyntaxError: wait n'est valide que dans la fonction async" (pour 'wait async.mapLimit')
Autre chose que je dois considérer ?
Le message d'erreur dit tout, wait n'est valide que dans une fonction asynchrone, jusqu'à ce que la proposition d'attente de niveau supérieur soit implémentée
Oui, je cherchais un exemple pleinement fonctionnel, car c'est vraiment la partie avec laquelle j'ai eu du mal. Peu importe, je l'ai enfin mis en service :
const myAsyncFunction = async function(){
//const numPromise = await async.mapLimit(['1','2','3','4','5'], 3, async num => delay(200).then(() => num*2))
const numPromise = await async.mapLimit(['1','2','3','4','5'], 3, async num => {
await delay(2000);
console.log(num*2);
return num*2;
})
//numPromise.then(console.log)
return numPromise;
}
myAsyncFunction()
.then((result) => console.log(result));
Je ne suis pas encore vraiment sûr de ce qui est différent des essais précédents, mais je validerai et ajouterai des conclusions supplémentaires à ce sujet.
Dans tous les cas, ce que je veux dire, c'est que tout cela n'est pas entièrement intuitif, je crois, donc des exemples comme celui-ci peuvent aider !
Et... je ne comprends toujours pas tout à fait pourquoi nous devons envelopper tous les async/attends autour, alors que async.mapLimit devrait simplement renvoyer une promesse simple par lui-même...
oups j'ai oublié un wait dans mon code précédent, édité
D'accord, maintenant je confirme pleinement :-) Donc, le problème principal était probablement que la fonction iteratee n'était pas entièrement asynchrone ?
Quoi qu'il en soit, cela fonctionne à merveille, semble-t-il, et c'est probablement aussi un excellent exemple ! Merci de rester avec moi !!
Voir https://github.com/caolan/async/issues/1673 pour savoir pourquoi
async.mapLimit(['1','2','3','4','5'], 3, async num => delay(200).then(() => num*2)) // works
async.mapLimit(['1','2','3','4','5'], 3, num => delay(200).then(() => num*2)) // doesn't work
Promise.all(['1','2','3','4','5'].map(num => delay(200).then(() => num*2))) // works (plain promises)
Je vois, vous êtes complètement avec moi, c'est-à-dire avez eu les mêmes problèmes.
Je suppose que mon point principal est vraiment le suivant - la documentation indique simplement "Retours: une promesse si aucun rappel n'est passé" - donc, quand j'ai la variante de rappel, et que je laisse simplement cela de côté, comment pourrais-je penser que j'ai besoin pour ajouter le mot-clé 'async' quand cela fonctionnait sans cela dans la version de rappel. De plus, en utilisant le module 'promise-async', cela fonctionne exactement comme je m'y attendais.
De plus, je n'ai pas encore compris pourquoi l'exemple 'Promise.all' ci-dessus fonctionne... c'est vraiment déroutant pour moi.
La fonction iteratee étant async
ou utilisant un rappel ne devrait pas affecter le retour d'une promesse si le rappel final est omis. C'est un bogue.
Je vous parie que c'est lié à #1685
Je vous parie que c'est lié à #1685
Je me souviens certainement d'avoir déjà eu ce problème dans certaines versions de mes exemples de code. J'ai supposé évidemment que cela était causé par un mauvais codage. Donc, intéressant de voir qu'il apparaît également dans une saveur différente.
J'ai examiné cela plus en détail.
mapLimit
fonctionne comme prévu. Je parierais que tous les problèmes que les gens voient ici sont dus aux limitations de la détection des fonctions de retour de promesse, ou aux compilateurs (par exemple babel, tapuscrit) ne préservant pas les fonctions async
.
J'ai examiné cela plus en détail.
mapLimit
fonctionne comme prévu. Je parierais que tous les problèmes que les gens voient ici sont dus aux limitations de la détection des fonctions de retour de promesse, ou aux compilateurs (par exemple babel, tapuscrit) ne préservant pas les fonctionsasync
.
Quelle est la meilleure façon de gérer de tels scénarios où async
n'est pas conservé sur les compilations ?
Enveloppez la fonction async
dans asyncify
. http://caolan.github.io/async/v3/global.html#AsyncFunction
Commentaire le plus utile