2017-09-24 2 views
0

J'essaie d'envelopper ma tête autour de Promises et comment les utiliser sur des boucles asynchrones.Comment utiliser Promise.all() et une boucle async?

Je réunis le code suivant pour lire le contenu de trois fichiers (en utilisant forEach) et lorsque toutes les promesses de résoudre journaliser les résultats de tous les fichiers:

var Promise = require('bluebird'); 
var fs = require('fs'); 
var path = require('path'); 

var files = ['1.json','2.json','3.json']; 
var promises = [] 

files.forEach(function(file){ 
    fs.readFile(path.join('./',file), 'utf8', function(err,data){ 
     promises.push(new Promise(function(resolve, reject){ 
      resolve(data) 
     }) 
       ); 
    }) 
}); 

Promise.all(promises).then(function(values){ 
    console.log(values) 
}); 

Je ne sais pas comment mettre la boucle à l'intérieur le .all()

J'ai essayé ce code mais cela enregistre un tableau vide.

Qu'est-ce que je fais mal?

+1

a) ne pas utiliser 'forEach' (mais mieux' map') b) vous êtes * 'push'ing * la promesse asynchrone, le tableau est vide quand' Promise.all' le reçoit. Construis la promesse immédiatement, et seulement * 'la résout * asynchrone – Bergi

Répondre

0

Utilisez .map() pour parcourir votre tableau, en commençant un appel asynchrone pour chacun d'entre eux, puis en renvoyant la promesse pour chaque appel. La valeur de retour de cette carte sera un nouveau tableau de promesses que vous pouvez ensuite passer à Promise.all().

let Promise = require('bluebird') 
let fs = Promise.promisifyAll(require('fs')) 

let promises = files.map((file) => { 
    // readFile will return promises because of bluebird promisifyAll 
    return fs.readFile(...) 
}) 

Promise.all(promises).then((results) => { 
    // results will be an array of all the files that were read 
    console.log(results); 
}); 
3

Vous mélangez callbacks avec des promesses, créer un tableau de promesses à l'aide Array#map et le transmettre à Promise.all:

var files = ['1.json', '2.json', '3.json']; 
var promises = files.map(file => { 
    return new Promise((resolve, reject) => { 
    fs.readFile(path.join('./',file), 'utf8', (err, data) => { 
     if (err) { 
     return reject(err); 
     } 
     resolve(data); 
    }); 
    }); 
}); 

Promise.all(promises).then(function(values){ 
    console.log(values) 
}); 
+0

Nice! Je vous remercie. Une autre question. Comment ce code changerait-il si la source du tableau des noms de fichiers était elle-même le résultat d'une fonction asynchrone? – medicengonzo

+0

Dans ce cas, vous devez ajouter la fonction de chargement des noms de fichiers à une chaîne de promesses (démarrer la chaîne de promesses à partir de cette fonction): 'getFilesNames(). Then (fileNames => Promise.all (fileNames.map (...))) .then (values ​​=> ...) ' – alexmac

+0

Alors, est-ce que je peux définir la fonction avant de l'appeler? En outre, il devrait renvoyer une promesse, correct? – medicengonzo