web-dev-qa-db-fra.com

Comment utiliser promise dans chaque boucle forEach du tableau pour renseigner un objet

J'exécute une boucle forEach sur un tableau et passe deux appels qui renvoient des promesses. Je souhaite remplir un objet, par exemple, this.options, puis effectuer d'autres opérations. À l'heure actuelle, je rencontre le problème asynchrone si j'utilise l'exemple de code suivant et que j'entre en premier dans la fonction then.

$.when.apply($, someArray.map(function(item) {
    return $.ajax({...}).then(function(data){...});
})).then(function() {
    // all ajax calls done now
});

C'est le code de travail ci-dessous, mais cela ne fonctionne que pour le premier élément du tableau, car j'appelle la fonction résultante dans le .then de la réponse. Je veux faire tout le fetch en premier pour tous les éléments du tableau, puis appeler la fonction résultante pour faire quelque chose.

array.forEach(function(element) {
    return developer.getResources(element)
        .then((data) = > {
            name = data.items[0];
            return developer.getResourceContent(element, file);
        })
        .then((response) = > {
            fileContent = atob(response.content);
            self.files.Push({
                fileName: fileName,
                fileType: fileType,
                content: fileContent
            });
            self.resultingFunction(self.files)
        }).catch ((error) = > {
            console.log('Error: ', error);
        })
});

Comment peupler l'objet self.files une fois la boucle forEach terminée, puis appeler la fonction résultante avec l'objet files? 

14
rond

Promise.all() sera utile ici:

var promises = [];

array.forEach(function(element) {
    promises.Push(
        developer.getResources(element)
            .then((data) = > {
                name = data.items[0];
                return developer.getResourceContent(element, file);
            })
            .then((response) = > {
                fileContent = atob(response.content);
                self.files.Push({
                    fileName: fileName,
                    fileType: fileType,
                    content: fileContent
                });
            }).catch ((error) = > {
                console.log('Error: ', error);
            })
    );
});

Promise.all(promises).then(() => 
    self.resultingFunction(self.files)
);

Cela démarre l'appel AJAX pour chacun des éléments, ajoute le résultat de chaque appel à self.files une fois l'appel terminé et appelle self.resultingFunction() une fois tous les appels terminés.

Edit: Simplifié sur la base des suggestions de Yury Tarabanko.

45
Timo

Une légère variation de la solution acceptée ci-dessus serait:

var promises = array.map(function(element) {
      return developer.getResources(element)
          .then((data) = > {
              name = data.items[0];
              return developer.getResourceContent(element, file);
          })
          .then((response) = > {
              fileContent = atob(response.content);
              self.files.Push({
                  fileName: fileName,
                  fileType: fileType,
                  content: fileContent
              });
          }).catch ((error) = > {
              console.log('Error: ', error);
          })
});

Promise.all(promises).then(() => 
    self.resultingFunction(self.files)
);
14
IonicBurger

Le code suivant est une compréhension simple de la synchronisation à l'aide de Promise.

let numArr = [1,2,3,4,5];
let nums=[];

let promiseList = new Promise(function(resolve,reject){
  setTimeout(()=>{
        numArr.forEach((val)=>{
        nums.Push(val);
    });
    resolve(nums);
 },5000)
})


Promise.all([promiseList]).then((arrList)=>{
  arrList.forEach((array)=>{
    console.log("Array return from promiseList object ",array);    
  })

 });

L'exemple ci-dessus tiendra array nums pendant 5 secondes. et il imprimera sur la console après sa sortie. 

1
jasmeetsohal

Vous pouvez regarder cette réponse à une question similaire pour un excellent indice. La solution donnée utilise ici Array#reduce() pour éviter de devoir accumuler toutes les promesses avant d’effectuer le travail au lieu d’utiliser Promise.all().

1
Alan Mimms