2016-08-25 1 views
-4

Je suis confronté à une situation de "rappel de l'enfer" dans Node.js.Callback hell dans Node.js

Au fond ce que je veux est:

données lues à partir d'un fichier JSON statique (local) -> requête MongoDB pour obtenir deux enregistrements de deux collections distinctes -> comparer les données renvoyées -> ajouter le résultat après comparer dans l'objet de résultat -> aller à l'étape suivante dans la boucle -> répéter.

S'il vous plaît examiner le code et laissez-moi savoir où est le problème.

jsonfile.readFile(file, function(err, staticData) { 
if(err){ 
    console.log("Error while loading Tower Details from Static Data " + err); 
} 
else{ 
    var staticD = staticData.Teams; 
    var l = staticData.Teams.length; 
// console.log('*******************Getting Tower Level Data from Static File*******************'); 
    //console.log('*******************Tower Name received is ******************* ' + staticData.Tower); 
     if(counter == l){ 
     console.log('Inside the couneter loop'); 
     res.json(testObject); 
     } 
    for (var i = 0 ; i<l; i++){ 
    var trackName = staticD[i].name 
    console.log('Counter--------->>>>' + counter); 
    //console.log("Team name " + staticD[i].name); 
     ++counter; 
    for (var j = 0 ; j<staticD[i].applications.length;j++){ 
    //var RObj; 
    //var AObj; 
     //console.log("Application Name " + staticD[i].applications[j]); 
     var applicationName = staticD[i].applications[j]; 
     var test = new Object(); 
     test.data = []; 
     var resultSet; 

    var response = reference.find({'appname' : applicationName , 'track' : trackName }).sort({'_id': -1}); 
    var promise = response.exec(); 
    var alertT = alert.find({'appname' : applicationName , 'track' : trackName }).sort({'_id': -1}).limit(1); 
    var promise1 = alertT.exec(); 

     promise.then(function allRefRecords (recordAlerts){ 
     if(recordAlerts.length >0){ 
      //console.log('Ref Length' + recordAlerts.length); 
     recordAlerts.forEach(function refRecord(R){ 
      testObject.data.testInfra.push(R); 
      //console.log('testObject' + testObject.data.testInfra); 
      }); 
    } 

      }); 

     promise1.then(function allAlertsRecords (alerts){ 
      if(alerts.length > 0){ 
     alerts.forEach(function refRecord(a){ 
     // console.log('a' + a) 
     testObject.data.testCustom.push(a); 
      //console.log('testObject' + testObject.data.testCustom); 
     // res.json(testObject); 

     }); 
     }   
      }) 
     .then(function(){ 
      resultSet = compareData(testObject.data.testCustom,testObject.data.testInfra); 
      test.data.push(resultSet); 
      }) 
     .then(function(){ 
      res.json(test); 
     }); 
    } 

    } 

} 

}); 

}); 
+1

Je vous suggère d'utiliser 'async' dans votre code, au lieu d'utiliser pour la boucle. – Shrabanee

+0

J'ai essayé les promesses dans le code, mais j'obtiens des résultats variables. Parfois, je reçois 2 enregistrements et parfois 3. – Harsh

Répondre

3

Ne met pas imbriquer des fonctions, leur donner des noms et de les placer au niveau supérieur de votre programme. Utilisez la fonction de levage à votre avantage pour déplacer les fonctions 'sous le pli'. Gérer chaque erreur dans de vos rappels et utiliser une norme comme linter pour vous aider avec cela. Créez des fonctions réutilisables et placez-les dans un module pour réduire la charge cognitive requise pour comprendre votre code. Diviser votre code en petits morceaux comme ceci vous aide également à gérer les erreurs, écrire tests, vous oblige à créer une API publique stable et documentée pour votre code, et aide à refactoring.

Source: http://callbackhell.com/

Il est possible d'éviter l'enfer de rappel avec ASYNC, avec PROMESSES, avec DESIGNS, et bien d'autres façons ... Mais 99% du temps, le design est le meilleur (AMHA) et vous n'avez pas besoin d'autres choses.

Quelques liens:
How to Elegantly Solve the Callback Hell
Avoiding Callback Hell in Node.js

Rappelez-vous que l'enfer de rappel est pas une fatalité;)

+0

J'ai essayé des promesses dans le code et maintenant je reçois les résultats. Cependant, le nombre d'enregistrements dans les résultats est aléatoire. Cela signifie parfois que je reçois 2 enregistrements et parfois 3 et c'est la réponse pour la même demande.Tout ce que je veux, c'est: obtenir un enregistrement de la collection de référence, puis en obtenir un de la collection d'alertes, puis comparer les deux objets récupérés à l'étape précédente et retourner le résultat. J'ajoute aussi des extraits de code. – Harsh

+0

Extrait de code # 1 response = reference.find ({'appname': nomapplication, 'track': trackName}). Sort ({'_ id': -1}); var promise; promesse = response.exec(); var alertT; alertT = alert.find ({'nomapplication: nomapplication,' suivi ': nompiste}). Sort ({' _ id ': -1}) .limit (1); var promise1; promesse1 = alertT.exec(); – Harsh

+0

extrait de code n ° 2: promise.then (fonction allRefRecords (recordAlerts) { if (recordAlerts.length == 1) { recordAlerts.forEach (fonction refRecord (R) { testObject.data.testInfra.push (R); }); } }); – Harsh

0

Quelques conseils pour éviter une apparence plus de Callback Enfer vous pouvez parcourir les bibliothèques suivantes:

  • Async.js: vous pouvez exécuter des fonctions en série sans les imbriquer.
  • Bluebird: La logique asynchrone sera plus facile à gérer avec le mappage et la mise en file d'attente.
  • Q: révèle le concept de promesse de gérer les appels imbriqués sans effort.

Si vous avez d'autres questions, vous pouvez trouver des réponses ici https://artjoker.net/blog/nodejs-essentials-keeping-its-benefits-in-order/