2017-09-19 3 views
0

J'utilise pour loop pour itérer sur un tableau d'éléments et pour appeler la même fonction avec différents paramètres à l'intérieur de la boucle for. Voici mon code:Comment attendre chaque itération dans la réponse de boucle et de retour en tant que réponse API dans nodeJS

exports.listTopSongs = function(query) { 
    return new Promise(function(resolve, reject) { 
     var str = query.split(","), category, 
     for(var i=0; i<str.length; i++) { 
      sampleFn(str[i], 'sample', resolve, reject); 
     } 
    }); 
}; 

function sampleFn(lang, cat, resolve, reject) { 
     client.on("error", function (err) { 
      console.log(err); 
      var err = new Error('Exception in redis client connection') 
      reject(err);         
     }); 
     client.keys(lang, function (err, keys){ 
      if (err) return console.log(err); 
      if(keys.length != 0) { 
       client.hgetall(keys, function (error, value) { 
        var objects = Object.keys(value); 
        result['title'] = lang; 
        result[cat] = []; 
        var x =0; 
        for(x; x<objects.length; x++) { 
         var val = objects[x]; 
          User.findAll({attributes: ['X', 'Y', 'Z'], 
           where: { 
            A: val 
           } 
          }).then(data => { 
           if(data != null) { 
            //some actions with data and stored it seperately in a Json array 
            if(result[cat].length == objects.length) { 
             resolve(result); 
            } 
           } else { 
            console.log(""+cat+" is not avilable for this value "+data.dataValues['X']); 
           } 
          }); 
        } 
       }); 
     }); 
    } 

Ici, il n'attendra pas la fin de la première itération. Il fonctionne juste de manière asynchrone avant de remplir la première fonction d'itération. Je dois retourner le résultat en résultat: [{1, 2}, {3,4}]. mais il fonctionne parfaitement et retourne vide ou seulement un objet avant de tout terminer. Comment le résoudre.

J'ai utilisé une boucle asynchrone de noeud. Mais il utilise ensuite et je ne peux pas envoyer mes paramètres en utilisant ce paquet. S'il vous plaît aidez-moi

+0

Vérifiez le paquet "aync". Il a beaucoup de fonctions qui font fonctionner la boucle de façon synchrone. –

+0

quelle version de noeud js vous utilisez? –

+0

J'utilise le noeud 8.4.0 –

Répondre

1

Async fournit des méthodes de flux de contrôle permettant de le faire.

En utilisant async.each:

async.each(openFiles, function(file, callback) { 

    // Perform operation on file here. 
    console.log('Processing file ' + file); 

    if(file.length > 32) { 
     console.log('This file name is too long'); 
     callback('File name too long'); 
    } else { 
     // Do work to process file here 
     console.log('File processed'); 
     callback(); 
    } 
}, function(err) { 
    // if any of the file processing produced an error, err would equal that error 
    if(err) { 
     // One of the iterations produced an error. 
     // All processing will now stop. 
     console.log('A file failed to process'); 
    } else { 
     console.log('All files have been processed successfully'); 
    } 
}); 
+0

pouvez-vous s'il vous plaît modifier mon code en utilisant async.each? –

0

Si vous ne souhaitez pas utiliser une bibliothèque, vous pouvez coder vous-même. Ce serait également très instructif. Je pris votre problème et codifiés une boucle async factice:

function listTopSongs(query) { 
 
    return new Promise(async(resolve, reject) => { //add async here in order to do asynchronous calls 
 
     const str = query.split(",") //str is const, and the other variable was not used anyway 
 
     
 
     for(let i = 0;i < str.length; i++) { 
 
      const planet = await sampleFn(str[i], 'sample', resolve, reject) 
 
      console.log(planet) 
 
     } 
 
    }); 
 
}; 
 

 
function sampleFn(a, b, c, d) { 
 
    return fetch(`https://swapi.co/api/planets/${a}/`) 
 
     .then(r => r.json()) 
 
     .then(rjson => (a + " : " + rjson.name)) 
 
} 
 

 
listTopSongs("1,2,3,4,5,6,7,8,9")

J'utilise une API star wars factice à une longue fausse promesse, mais il devrait fonctionner avec votre sampleFn. Attention, c'est très, très lent si vous avez un appel réseau comme celui de l'exemple.

EDIT: Je couru votre code et je remarquai il y a quelques erreurs: il n'y a pas la volonté de votre promesse si ce n'est pas un thenable (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/resolvevoir thenable)

Voici un code de travail entièrement . La belle partie: pas de bibliothèque nécessaire, pas de dépendances.

//for node.js, use node-fetch : 
 
//const fetch = require("node-fetch") 
 

 
function listTopSongs(query) { 
 
    return new Promise(async(resolve, reject) => { //add async here in order to do asynchronous calls 
 
     const str = query.split(",") //str is const, and the other variable was not used anyway 
 
     const planets = [] 
 
     for (let i = 0; i < str.length; i++) { 
 
      const planet = await sampleFn(i + 1, str[i], resolve, reject) 
 
      planets[i] = planet 
 
      console.log(planet) 
 
     } 
 
     resolve(planets) 
 
    }); 
 
}; 
 

 
function sampleFn(a, b, c, d) { 
 
    return fetch(`https://swapi.co/api/planets/${a}/`) 
 
     .then(r => r.json()) 
 
     .then(rjson => (a + b + " : " + rjson.name)) 
 
} 
 

 
listTopSongs("a,b,c,d").then(planets => console.log(planets))

+0

Je ne peux pas renvoyer mon tableau json de la fonction sampleFn à listTopSongs –

0

Puisque vous utilisez la promesse, vous pouvez faire quelque chose comme ça

exports.listTopSongs = function(query) { 
    return Promise.resolve(true).then(function(){ 
     var str = query.split(","); 
     var promises = str.map(function(s){ 
      return sampleFn(str[i], 'sample'); 
     }); 
     return Promise.all(promises); 
    }).then(function(results){ 
     //whatever you want to do with the result 
    }); 
}; 

Pour cela fonctionne, vous devez changer votre sampleFn de ne pas dépendre externe résoudre et rejeter les fonctions. Je ne vois pas de raison d'utiliser la résolution externe et de rejeter. pourquoi ne pas utiliser Promise.Resolve, Promise.Reject;