Je ne peux toujours pas envelopper mon esprit autour de la fonctionnalité Async / attendre et j'ai essayé plusieurs solutions sans succès pour le scénario suivant:
J'ai cette fonction: p>
c.on('drain', async function () { Database.addDataToDb(ArticleList); console.log("All done"); });
3 Réponses :
Si vous pouviez, essayez ceci,
const saveData = (articleItem) => { return new Promise((resolve, reject) => { var article = new SiteUrlModel(articleItem).save(function (error) { if (error) { console.log("Failed: " + articleItem.siteName); reject(error); } else { console.log("Success " + articleItem.siteName); resolve('Success'); } }); }); }); const addDataToDb = (articleData) => { const list = []; return new Promise((resolve, reject) => { initMongoDb(); kanpionDb.on('error', console.error.bind(console, 'connection error:')); kanpionDb.once('open', function () { SiteUrlModel.init().then(() => { articleData.forEach(articleItem => { list.push(saveData(articleItem); }); }); }); Promise.all(list).then(response => { resolve(response); }).catch(error => { reject(error); }) }); }; c.on('drain', async function () { const result = Database.addDataToDb(ArticleList).then(res => { console.log("All done"); }); });
Vous avez un résolution () code> et
rejet () code> à l'intérieur d'un
.foreach () code>. Cela ne fonctionnera pas correctement. Il résoudra la promesse sur la première itération de la boucle
Ov .Ovoir () code> et n'attendra pas que la boucle se termine.
@ Jfrage00 merci d'avoir souligné cela. Je pensais que je faisais juste donner l'idée de l'utilisation des promesses que j'avais à l'esprit.
Votre nouveau code évolue dans la bonne direction, mais il va appeler promess.all (liste) code> avant la liste
code> a quelque chose en elle.
Je pense que vous ne travaillerez que si la liste a une longueur
La liste code> list code> sera vide lorsque vous appelez promess.all (liste) code> de sorte qu'il ne pourra donc pas attendre le
.foreseach () code> boucle à faire.
Vous pouvez utiliser des promesses pour que l'appelant attendait que votre code ASYNC soit terminé. Refactor votre addDaTatoToToDB code> pour renvoyer une promesse et résoudre / rejeter la promesse en conséquence. Comme vous avez défini le rappel "Drain" pour être une fonction ASYNC, vous pouvez utiliser le mot-clé code> attendre code> à l'intérieur de votre rappel pour rendre les choses un peu plus concises:
C'est l'une des solutions que j'ai essayées, mais je n'ai pas travaillé. @ jfriend00 réponse a fonctionné super.
Cette solution est une sorte de désordre, car vous avez un gros mélange de techniques asynchrones toutes mélangées dans la même fonction: événements, promesses et rappels, puis en haut de cela, il y a une boucle. C'est en effet un désordre et est généralement quelque chose que vous voulez éviter.
La meilleure solution globale à ce niveau de complication est de sauvegarder quelques étapes et d'acquérir toutes les opérations asynchrones de base quelques étapes plus élevées que cela. Pour votre base de données, vous devriez aller chercher et utiliser l'interface de promesse vers la base de données. Pour vos événements, car ils sont tous deux des événements uniques, vous pouvez construire une enveloppe de promesse sur l'objet pour vous être averti pour les événements Open and Error. P>
Mais, puisque je ne connais pas tous les composants que vous avez J'utilise, je ne peux pas vraiment faire cette partie de cela pour vous. Nous allons donc examiner ce que nous pouvions faire pour corriger un support de niveau de promesse approprié dans ce mélange de techniques. P> Résumé des techniques: P>
.foForeach () code> boucle est remplacé par
promess.Tous (articledata.map (...)) code> qui nous donnera une promesse qui nous dit une promesse qui nous dit quand tout Les sauvegardes sont terminées. LI>
.Save (rappel) code> doit être remplacé par une version promis de
.Save () code>. Idéalement, vous allez simplement utiliser une version promis de votre interface de base de données ici, mais j'ai montré comment promouvoir manuellement le
.Save () code> fonction si nécessaire. Li>
Siteurlmodel.init () Code> Promesse. Li>
promess.all () code> promets du
Siteurlmodel.init () code> Promesse. Li>
ol> p>
J'essayais juste maintenant parce que j'étais éteint toute la matinée. Merci beaucoup pour l'explication détaillée et approfondie de tout. Cela a fonctionné brillamment. Je dois maintenant mettre ce que vous avez fait dans un tableau noir et disséquer. Je pense que cela me placera dans un excellent chemin pour comprendre cela.
Je n'ai pas eu à réparer quoi que ce soit. Il vient de se brancher directement.
En le mettant à la fin de la chaîne ASYNC? Par exemple. Après cet ensemble
articledata.foreach () code> bloc? Cependant, ce que vous voulez probablement faire est de faire de cette déclaration une promesse qui se résout ou passe dans un rappel, puis de l'exécuter une fois que vous avez atteint ce point.