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?
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.
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)
);
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.
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()
.